chore: 补充 satellite 网络类型、升级测试资源与依赖锁定

- bridge_actions: 新增 ConnectivityResult.satellite 分支映射
- test_assets: 更新 bootstrap/config 测试资源与 bridge 调试页面
- apps: 同步 pubspec.lock 依赖锁定
- flavors: 更新 test.yaml 配置
This commit is contained in:
Max 2026-04-02 14:28:19 +08:00
parent c1d2db1d60
commit ce3122861c
9 changed files with 355 additions and 152 deletions

View File

@ -13,10 +13,10 @@ packages:
dependency: transitive
description:
name: async
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.13.0"
version: "2.13.1"
boolean_selector:
dependency: transitive
description:
@ -61,18 +61,18 @@ packages:
dependency: transitive
description:
name: connectivity_plus
sha256: "33bae12a398f841c6cda09d1064212957265869104c478e5ad51e2fb26c3973c"
sha256: b8fe52979ff12432ecf8f0abf6ff70410b1bb734be1c9e4f2f86807ad7166c79
url: "https://pub.flutter-io.cn"
source: hosted
version: "7.0.0"
version: "7.1.0"
connectivity_plus_platform_interface:
dependency: transitive
description:
name: connectivity_plus_platform_interface
sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204"
sha256: "3c09627c536d22fd24691a905cdd8b14520de69da52c7a97499c8be5284a32ed"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.1"
version: "2.1.0"
cross_file:
dependency: transitive
description:
@ -93,10 +93,10 @@ packages:
dependency: "direct main"
description:
name: cupertino_icons
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.8"
version: "1.0.9"
dbus:
dependency: transitive
description:
@ -109,10 +109,10 @@ packages:
dependency: transitive
description:
name: device_info_plus
sha256: "4df8babf73058181227e18b08e6ea3520cf5fc5d796888d33b7cb0f33f984b7c"
sha256: b4fed1b2835da9d670d7bed7db79ae2a94b0f5ad6312268158a9b5479abbacdd
url: "https://pub.flutter-io.cn"
source: hosted
version: "12.3.0"
version: "12.4.0"
device_info_plus_platform_interface:
dependency: transitive
description:
@ -223,10 +223,10 @@ packages:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
sha256: ee8068e0e1cd16c4a82714119918efdeed33b3ba7772c54b5d094ab53f9b7fd1
sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.33"
version: "2.0.34"
flutter_test:
dependency: "direct dev"
description: flutter
@ -281,10 +281,10 @@ packages:
dependency: transitive
description:
name: image_picker_android
sha256: eda9b91b7e266d9041084a42d605a74937d996b87083395c5e47835916a86156
sha256: "9eae0cbd672549dacc18df855c2a23782afe4854ada5190b7d63b30ee0b0d3fd"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.8.13+14"
version: "0.8.13+15"
image_picker_for_web:
dependency: transitive
description:
@ -441,10 +441,10 @@ packages:
dependency: transitive
description:
name: package_info_plus
sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d
sha256: "468c26b4254ab01979fa5e4a98cb343ea3631b9acee6f21028997419a80e1a20"
url: "https://pub.flutter-io.cn"
source: hosted
version: "9.0.0"
version: "9.0.1"
package_info_plus_platform_interface:
dependency: transitive
description:
@ -473,10 +473,10 @@ packages:
dependency: transitive
description:
name: path_provider_android
sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e
sha256: "149441ca6e4f38193b2e004c0ca6376a3d11f51fa5a77552d8bd4d2b0c0912ba"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.22"
version: "2.2.23"
path_provider_foundation:
dependency: transitive
description:
@ -593,18 +593,18 @@ packages:
dependency: transitive
description:
name: shared_preferences
sha256: "2939ae520c9024cb197fc20dee269cd8cdbf564c8b5746374ec6cacdc5169e64"
sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.5.4"
version: "2.5.5"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: "8374d6200ab33ac99031a852eba4c8eb2170c4bf20778b3e2c9eccb45384fb41"
sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.21"
version: "2.4.23"
shared_preferences_foundation:
dependency: transitive
description:
@ -625,10 +625,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.1"
version: "2.4.2"
shared_preferences_web:
dependency: transitive
description:
@ -718,10 +718,10 @@ packages:
dependency: transitive
description:
name: url_launcher_android
sha256: "767344bf3063897b5cf0db830e94f904528e6dd50a6dfaf839f0abf509009611"
sha256: "3bb000251e55d4a209aa0e2e563309dc9bb2befea2295fd0cec1f51760aac572"
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.3.28"
version: "6.3.29"
url_launcher_ios:
dependency: transitive
description:
@ -813,26 +813,26 @@ packages:
dependency: transitive
description:
name: webview_flutter_android
sha256: "2a03df01df2fd30b075d1e7f24c28aee593f2e5d5ac4c3c4283c5eda63717b24"
sha256: "0f7fcd2c86bf36bdcf94881f7941ce0cbc4f8d104b9fdcd5fcbef90e2199db76"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.10.13"
version: "4.10.15"
webview_flutter_platform_interface:
dependency: transitive
description:
name: webview_flutter_platform_interface
sha256: "63d26ee3aca7256a83ccb576a50272edd7cfc80573a4305caa98985feb493ee0"
sha256: "1221c1b12f5278791042f2ec2841743784cf25c5a644e23d6680e5d718824f04"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.14.0"
version: "2.15.1"
webview_flutter_wkwebview:
dependency: transitive
description:
name: webview_flutter_wkwebview
sha256: "0d85e8bc5db9a7c49f6ff57cbeafc6cd8216ad9c9ebc70b2c4579d955698933a"
sha256: d7219cfabc6f5fc2032e0fa980ec36d71f308a35a823395af1abc34d9a2ede83
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.24.1"
version: "3.24.2"
win32:
dependency: transitive
description:

View File

@ -1,5 +1,5 @@
{
"initialUrl": "http://192.168.2.57:8080/test_bridge.html",
"initialUrl": "http://192.168.2.200:8080/test_bridge.html",
"preferredOrientations": [
"portraitUp",
"portraitDown"

View File

@ -13,10 +13,10 @@ packages:
dependency: transitive
description:
name: async
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.13.0"
version: "2.13.1"
boolean_selector:
dependency: transitive
description:
@ -61,18 +61,18 @@ packages:
dependency: transitive
description:
name: connectivity_plus
sha256: "33bae12a398f841c6cda09d1064212957265869104c478e5ad51e2fb26c3973c"
sha256: b8fe52979ff12432ecf8f0abf6ff70410b1bb734be1c9e4f2f86807ad7166c79
url: "https://pub.flutter-io.cn"
source: hosted
version: "7.0.0"
version: "7.1.0"
connectivity_plus_platform_interface:
dependency: transitive
description:
name: connectivity_plus_platform_interface
sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204"
sha256: "3c09627c536d22fd24691a905cdd8b14520de69da52c7a97499c8be5284a32ed"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.1"
version: "2.1.0"
cross_file:
dependency: transitive
description:
@ -93,10 +93,10 @@ packages:
dependency: "direct main"
description:
name: cupertino_icons
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.8"
version: "1.0.9"
dbus:
dependency: transitive
description:
@ -109,10 +109,10 @@ packages:
dependency: transitive
description:
name: device_info_plus
sha256: "4df8babf73058181227e18b08e6ea3520cf5fc5d796888d33b7cb0f33f984b7c"
sha256: b4fed1b2835da9d670d7bed7db79ae2a94b0f5ad6312268158a9b5479abbacdd
url: "https://pub.flutter-io.cn"
source: hosted
version: "12.3.0"
version: "12.4.0"
device_info_plus_platform_interface:
dependency: transitive
description:
@ -223,10 +223,10 @@ packages:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
sha256: ee8068e0e1cd16c4a82714119918efdeed33b3ba7772c54b5d094ab53f9b7fd1
sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.33"
version: "2.0.34"
flutter_test:
dependency: "direct dev"
description: flutter
@ -281,10 +281,10 @@ packages:
dependency: transitive
description:
name: image_picker_android
sha256: eda9b91b7e266d9041084a42d605a74937d996b87083395c5e47835916a86156
sha256: "9eae0cbd672549dacc18df855c2a23782afe4854ada5190b7d63b30ee0b0d3fd"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.8.13+14"
version: "0.8.13+15"
image_picker_for_web:
dependency: transitive
description:
@ -441,10 +441,10 @@ packages:
dependency: transitive
description:
name: package_info_plus
sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d
sha256: "468c26b4254ab01979fa5e4a98cb343ea3631b9acee6f21028997419a80e1a20"
url: "https://pub.flutter-io.cn"
source: hosted
version: "9.0.0"
version: "9.0.1"
package_info_plus_platform_interface:
dependency: transitive
description:
@ -473,10 +473,10 @@ packages:
dependency: transitive
description:
name: path_provider_android
sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e
sha256: "149441ca6e4f38193b2e004c0ca6376a3d11f51fa5a77552d8bd4d2b0c0912ba"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.22"
version: "2.2.23"
path_provider_foundation:
dependency: transitive
description:
@ -593,18 +593,18 @@ packages:
dependency: transitive
description:
name: shared_preferences
sha256: "2939ae520c9024cb197fc20dee269cd8cdbf564c8b5746374ec6cacdc5169e64"
sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.5.4"
version: "2.5.5"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: "8374d6200ab33ac99031a852eba4c8eb2170c4bf20778b3e2c9eccb45384fb41"
sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.21"
version: "2.4.23"
shared_preferences_foundation:
dependency: transitive
description:
@ -625,10 +625,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.1"
version: "2.4.2"
shared_preferences_web:
dependency: transitive
description:
@ -718,10 +718,10 @@ packages:
dependency: transitive
description:
name: url_launcher_android
sha256: "767344bf3063897b5cf0db830e94f904528e6dd50a6dfaf839f0abf509009611"
sha256: "3bb000251e55d4a209aa0e2e563309dc9bb2befea2295fd0cec1f51760aac572"
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.3.28"
version: "6.3.29"
url_launcher_ios:
dependency: transitive
description:
@ -813,26 +813,26 @@ packages:
dependency: transitive
description:
name: webview_flutter_android
sha256: "2a03df01df2fd30b075d1e7f24c28aee593f2e5d5ac4c3c4283c5eda63717b24"
sha256: "0f7fcd2c86bf36bdcf94881f7941ce0cbc4f8d104b9fdcd5fcbef90e2199db76"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.10.13"
version: "4.10.15"
webview_flutter_platform_interface:
dependency: transitive
description:
name: webview_flutter_platform_interface
sha256: "63d26ee3aca7256a83ccb576a50272edd7cfc80573a4305caa98985feb493ee0"
sha256: "1221c1b12f5278791042f2ec2841743784cf25c5a644e23d6680e5d718824f04"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.14.0"
version: "2.15.1"
webview_flutter_wkwebview:
dependency: transitive
description:
name: webview_flutter_wkwebview
sha256: "0d85e8bc5db9a7c49f6ff57cbeafc6cd8216ad9c9ebc70b2c4579d955698933a"
sha256: d7219cfabc6f5fc2032e0fa980ec36d71f308a35a823395af1abc34d9a2ede83
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.24.1"
version: "3.24.2"
win32:
dependency: transitive
description:

View File

@ -13,10 +13,10 @@ packages:
dependency: transitive
description:
name: async
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.13.0"
version: "2.13.1"
boolean_selector:
dependency: transitive
description:
@ -61,18 +61,18 @@ packages:
dependency: transitive
description:
name: connectivity_plus
sha256: "33bae12a398f841c6cda09d1064212957265869104c478e5ad51e2fb26c3973c"
sha256: b8fe52979ff12432ecf8f0abf6ff70410b1bb734be1c9e4f2f86807ad7166c79
url: "https://pub.flutter-io.cn"
source: hosted
version: "7.0.0"
version: "7.1.0"
connectivity_plus_platform_interface:
dependency: transitive
description:
name: connectivity_plus_platform_interface
sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204"
sha256: "3c09627c536d22fd24691a905cdd8b14520de69da52c7a97499c8be5284a32ed"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.1"
version: "2.1.0"
cross_file:
dependency: transitive
description:
@ -93,10 +93,10 @@ packages:
dependency: "direct main"
description:
name: cupertino_icons
sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6
sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.8"
version: "1.0.9"
dbus:
dependency: transitive
description:
@ -109,10 +109,10 @@ packages:
dependency: transitive
description:
name: device_info_plus
sha256: "4df8babf73058181227e18b08e6ea3520cf5fc5d796888d33b7cb0f33f984b7c"
sha256: b4fed1b2835da9d670d7bed7db79ae2a94b0f5ad6312268158a9b5479abbacdd
url: "https://pub.flutter-io.cn"
source: hosted
version: "12.3.0"
version: "12.4.0"
device_info_plus_platform_interface:
dependency: transitive
description:
@ -223,10 +223,10 @@ packages:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
sha256: ee8068e0e1cd16c4a82714119918efdeed33b3ba7772c54b5d094ab53f9b7fd1
sha256: "38d1c268de9097ff59cf0e844ac38759fc78f76836d37edad06fa21e182055a0"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.33"
version: "2.0.34"
flutter_test:
dependency: "direct dev"
description: flutter
@ -281,10 +281,10 @@ packages:
dependency: transitive
description:
name: image_picker_android
sha256: eda9b91b7e266d9041084a42d605a74937d996b87083395c5e47835916a86156
sha256: "9eae0cbd672549dacc18df855c2a23782afe4854ada5190b7d63b30ee0b0d3fd"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.8.13+14"
version: "0.8.13+15"
image_picker_for_web:
dependency: transitive
description:
@ -441,10 +441,10 @@ packages:
dependency: transitive
description:
name: package_info_plus
sha256: f69da0d3189a4b4ceaeb1a3defb0f329b3b352517f52bed4290f83d4f06bc08d
sha256: "468c26b4254ab01979fa5e4a98cb343ea3631b9acee6f21028997419a80e1a20"
url: "https://pub.flutter-io.cn"
source: hosted
version: "9.0.0"
version: "9.0.1"
package_info_plus_platform_interface:
dependency: transitive
description:
@ -473,10 +473,10 @@ packages:
dependency: transitive
description:
name: path_provider_android
sha256: f2c65e21139ce2c3dad46922be8272bb5963516045659e71bb16e151c93b580e
sha256: "149441ca6e4f38193b2e004c0ca6376a3d11f51fa5a77552d8bd4d2b0c0912ba"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.22"
version: "2.2.23"
path_provider_foundation:
dependency: transitive
description:
@ -593,18 +593,18 @@ packages:
dependency: transitive
description:
name: shared_preferences
sha256: "2939ae520c9024cb197fc20dee269cd8cdbf564c8b5746374ec6cacdc5169e64"
sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.5.4"
version: "2.5.5"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: "8374d6200ab33ac99031a852eba4c8eb2170c4bf20778b3e2c9eccb45384fb41"
sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.21"
version: "2.4.23"
shared_preferences_foundation:
dependency: transitive
description:
@ -625,10 +625,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.1"
version: "2.4.2"
shared_preferences_web:
dependency: transitive
description:
@ -718,10 +718,10 @@ packages:
dependency: transitive
description:
name: url_launcher_android
sha256: "767344bf3063897b5cf0db830e94f904528e6dd50a6dfaf839f0abf509009611"
sha256: "3bb000251e55d4a209aa0e2e563309dc9bb2befea2295fd0cec1f51760aac572"
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.3.28"
version: "6.3.29"
url_launcher_ios:
dependency: transitive
description:
@ -813,26 +813,26 @@ packages:
dependency: transitive
description:
name: webview_flutter_android
sha256: "2a03df01df2fd30b075d1e7f24c28aee593f2e5d5ac4c3c4283c5eda63717b24"
sha256: "0f7fcd2c86bf36bdcf94881f7941ce0cbc4f8d104b9fdcd5fcbef90e2199db76"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.10.13"
version: "4.10.15"
webview_flutter_platform_interface:
dependency: transitive
description:
name: webview_flutter_platform_interface
sha256: "63d26ee3aca7256a83ccb576a50272edd7cfc80573a4305caa98985feb493ee0"
sha256: "1221c1b12f5278791042f2ec2841743784cf25c5a644e23d6680e5d718824f04"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.14.0"
version: "2.15.1"
webview_flutter_wkwebview:
dependency: transitive
description:
name: webview_flutter_wkwebview
sha256: "0d85e8bc5db9a7c49f6ff57cbeafc6cd8216ad9c9ebc70b2c4579d955698933a"
sha256: d7219cfabc6f5fc2032e0fa980ec36d71f308a35a823395af1abc34d9a2ede83
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.24.1"
version: "3.24.2"
win32:
dependency: transitive
description:

View File

@ -1,7 +1,7 @@
app_name: "测试壳工程"
application_id: "com.yuanxuan.test_shell"
app_key: "test_shell"
default_url: "http://192.168.2.57:8080/test_bridge.html"
default_url: "http://192.168.2.200:8080/test_bridge.html"
bootstrap_config_url: ""
upgrade_config_url: ""
preferred_orientations:

View File

@ -39,6 +39,8 @@ Future<Map<String, dynamic>> _getNetworkStatusFromBridge() async {
type = 'vpn';
case ConnectivityResult.none:
type = 'none';
case ConnectivityResult.satellite:
type = 'satellite';
case ConnectivityResult.other:
type = 'unknown';
}

View File

@ -2,7 +2,10 @@
"code": 200,
"msg": "success",
"data": {
"initialUrl": "http://192.168.2.57:8080/test_bridge.html",
"preferredOrientations": ["portraitUp", "portraitDown"]
"initialUrl": "http://192.168.2.200:8080/test_bridge.html",
"preferredOrientations": [
"portraitUp",
"portraitDown"
]
}
}

View File

@ -2,7 +2,7 @@
"code": 200,
"msg": "success",
"data": {
"initialUrl": "http://192.168.2.57:8080/test_bridge.html",
"initialUrl": "http://192.168.2.200:8080/test_bridge.html",
"versionName": "1.0.0",
"version": 100,
"isForce": 0,

View File

@ -127,6 +127,14 @@
margin: 4px;
vertical-align: middle;
}
.preview-area video {
max-width: 160px;
max-height: 120px;
border-radius: 6px;
margin: 4px;
vertical-align: middle;
background: #000;
}
/* ── 原生 <a> 标签区域 ── */
.link-row {
@ -277,19 +285,43 @@
<div class="preview-area" id="pickImagePreview">选图结果将在此显示</div>
</div>
<!-- ══════════ 5. pickFile ══════════ -->
<div class="section-title">5. 文件选择 pickFile</div>
<!-- ══════════ 5. captureVideo ══════════ -->
<div class="section-title">5. 录像 captureVideo</div>
<div class="card">
<div class="btn-row">
<button onclick="testPickFile(false, 'uri')">📄 单选 uri</button>
<button onclick="testPickFile(true, 'uri')">📄 多选 uri</button>
<button class="secondary" onclick="testPickFile(false, 'dataUrl')">📄 单选 dataUrl</button>
<button onclick="testCaptureVideo()">🎥 录像</button>
</div>
<div class="preview-area" id="captureVideoPreview">录像结果将在此显示</div>
</div>
<!-- ══════════ 6. pickVideo ══════════ -->
<div class="section-title">6. 图库选视频 pickVideo</div>
<div class="card">
<div class="btn-row">
<button onclick="testPickVideo(false)">🎬 单选</button>
<button onclick="testPickVideo(true)">🎬 多选</button>
</div>
<div class="preview-area" id="pickVideoPreview">选视频结果将在此显示</div>
</div>
<!-- ══════════ 7. pickFile ══════════ -->
<div class="section-title">7. 文件选择 pickFile</div>
<div class="card">
<div class="card-label">通用文件与媒体 accept 场景</div>
<div class="btn-row">
<button onclick="testPickFile(false, 'uri')">📄 任意单选</button>
<button onclick="testPickFile(true, 'uri')">📄 任意多选</button>
<button class="secondary" onclick="testPickFileWithOptions({ accept: 'image/*', responseType: 'uri' }, '广义图片')">🖼 图片</button>
<button class="secondary" onclick="testPickFileWithOptions({ accept: 'video/*', responseType: 'uri' }, '广义视频')">🎬 视频</button>
<button class="secondary" onclick="testPickFileWithOptions({ accept: 'image/*,video/*', responseType: 'uri' }, '混合媒体')">🖼🎬 混合</button>
<button class="warn" onclick="testPickFileWithOptions({ accept: 'image/*', capture: true, responseType: 'uri' }, '图片 capture')">📸 图片 capture</button>
<button class="warn" onclick="testPickFileWithOptions({ accept: 'video/*', capture: true, responseType: 'uri' }, '视频 capture')">🎥 视频 capture</button>
</div>
<div class="preview-area" id="pickFilePreview">文件信息将在此显示</div>
</div>
<!-- ══════════ 6. openExternal ══════════ -->
<div class="section-title">6. 外部链接 openExternal</div>
<!-- ══════════ 8. openExternal ══════════ -->
<div class="section-title">8. 外部链接 openExternal</div>
<div class="card">
<div class="btn-row">
<button onclick="testOpenExternal('tel:10086')">📞 tel:10086</button>
@ -300,8 +332,8 @@
<div class="preview-area" id="externalPreview">调用结果将在此显示</div>
</div>
<!-- ══════════ 7. requestPermissions ══════════ -->
<div class="section-title">7. 权限请求 requestPermissions</div>
<!-- ══════════ 9. requestPermissions ══════════ -->
<div class="section-title">9. 权限请求 requestPermissions</div>
<div class="card">
<div class="btn-row">
<button onclick="testPermissions(['camera', 'microphone', 'location'])">🔐 常用三权限</button>
@ -312,8 +344,8 @@
<div class="preview-area" id="permPreview">权限状态将在此显示</div>
</div>
<!-- ══════════ 8. 页面控制 ══════════ -->
<div class="section-title">8. 页面控制</div>
<!-- ══════════ 10. 页面控制 ══════════ -->
<div class="section-title">10. 页面控制</div>
<div class="card">
<div class="btn-row">
<button onclick="testReload()">🔄 reloadPage</button>
@ -322,8 +354,18 @@
</div>
</div>
<!-- ══════════ 8.5 Phase 2: 新增能力 ══════════ -->
<div class="section-title">8.5 设备信息 getDeviceInfo</div>
<!-- ══════════ 10.5 运行时配置 ══════════ -->
<div class="section-title">10.5 运行时配置</div>
<div class="card">
<div class="btn-row">
<button onclick="testReloadUpgradeRuntimeConfig()">♻️ reloadUpgradeRuntimeConfig</button>
<button class="secondary" onclick="testReloadUpgradeRuntimeConfigAndCheckVersion(true)">🆙 reload + checkVersion</button>
</div>
<div class="preview-area" id="runtimeConfigPreview">运行时配置快照将在此显示</div>
</div>
<!-- ══════════ 11. 设备信息 ══════════ -->
<div class="section-title">11. 设备信息 getDeviceInfo</div>
<div class="card">
<div class="btn-row">
<button onclick="testGetDeviceInfo()">📱 获取设备信息</button>
@ -331,7 +373,7 @@
<div class="preview-area" id="deviceInfoBridgePreview">点击按钮通过 Bridge 获取完整设备信息</div>
</div>
<div class="section-title">8.6 网络状态 getNetworkStatus</div>
<div class="section-title">12. 网络状态 getNetworkStatus</div>
<div class="card">
<div class="btn-row">
<button onclick="testGetNetworkStatus()">📡 获取网络状态</button>
@ -339,7 +381,7 @@
<div class="preview-area" id="networkPreview">点击按钮获取当前网络连接类型</div>
</div>
<div class="section-title">8.7 原生 Toast showToast</div>
<div class="section-title">13. 原生 Toast showToast</div>
<div class="card">
<div class="btn-row">
<button onclick="testShowToast('short')">💬 短 Toast</button>
@ -347,7 +389,7 @@
</div>
</div>
<div class="section-title">8.8 状态栏控制 setStatusBar</div>
<div class="section-title">14. 状态栏控制 setStatusBar</div>
<div class="card">
<div class="btn-row">
<button onclick="testSetStatusBar('light')">☀️ 亮色图标</button>
@ -357,8 +399,8 @@
</div>
</div>
<!-- ══════════ 9. 旧相机兼容层 ══════════ -->
<div class="section-title">9. 旧相机兼容层 Legacy Camera</div>
<!-- ══════════ 15. 旧相机兼容层 ══════════ -->
<div class="section-title">15. 旧相机兼容层 Legacy Camera</div>
<div class="card">
<div class="card-label">openCamera / capturePhoto 劫持测试</div>
<div class="btn-row">
@ -371,20 +413,23 @@
<div class="preview-area" id="legacyPreview">旧相机兼容测试结果将在此显示</div>
</div>
<!-- ══════════ 10. 原生 <input type="file"> ══════════ -->
<div class="section-title">10. 原生 &lt;input type="file"&gt;</div>
<!-- ══════════ 16. 原生 <input type="file"> ══════════ -->
<div class="section-title">16. 原生 &lt;input type="file"&gt;</div>
<div class="card">
<div class="file-input-group">
<label>🖼 图片 (image/*)<input type="file" accept="image/*" onchange="handleFileInput(this, 'nativeFilePreview')"></label>
<label>📸 拍照 (capture)<input type="file" accept="image/*" capture onchange="handleFileInput(this, 'nativeFilePreview')"></label>
<label>🎬 视频 (video/*)<input type="file" accept="video/*" onchange="handleFileInput(this, 'nativeFilePreview')"></label>
<label>🎥 录像 (capture)<input type="file" accept="video/*" capture onchange="handleFileInput(this, 'nativeFilePreview')"></label>
<label>🖼🎬 混合媒体<input type="file" accept="image/*,video/*" onchange="handleFileInput(this, 'nativeFilePreview')"></label>
<label>📄 多文件 (multiple)<input type="file" multiple onchange="handleFileInput(this, 'nativeFilePreview')"></label>
<label>📁 任意文件<input type="file" onchange="handleFileInput(this, 'nativeFilePreview')"></label>
</div>
<div class="preview-area" id="nativeFilePreview">通过原生 &lt;input&gt; 选择文件后显示信息</div>
</div>
<!-- ══════════ 11. UI 状态观察 ══════════ -->
<div class="section-title">11. UI 状态观察(手动操作)</div>
<!-- ══════════ 17. UI 状态观察 ══════════ -->
<div class="section-title">17. UI 状态观察(手动操作)</div>
<div class="card">
<div class="card-label">以下由测试人员手动操作并观察壳应用行为:</div>
<ul style="padding-left:18px; font-size:13px; color:var(--muted); line-height:2;">
@ -438,6 +483,48 @@ function setPreview(id, html) {
document.getElementById(id).innerHTML = html;
}
function escapeAttribute(str) {
return String(str)
.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}
function normalizeBridgeItems(result) {
if (result == null) {
return [];
}
return Array.isArray(result) ? result : [result];
}
function buildBridgeMediaPreviewHtml(title, items) {
let html = `<b>${escapeHtml(title)}</b><br>`;
items.forEach((item, index) => {
const name = escapeHtml(item.name || '-');
const mimeType = escapeHtml(item.mimeType || '-');
const uri = escapeHtml(item.uri || '-');
const size = item.size || '-';
const hasBase64 = !!item.base64;
const hasDataUrl = !!item.dataUrl;
const source = item.dataUrl || item.uri || '';
html += `${index + 1}. <b>${name}</b> | ${mimeType} | ${size} bytes<br>`;
html += `uri: ${uri}<br>`;
html += `base64: ${hasBase64 ? '✅' : '—'} | dataUrl: ${hasDataUrl ? '✅' : '—'}<br>`;
if (source && typeof item.mimeType === 'string') {
if (item.mimeType.startsWith('image/')) {
html += `<img src="${escapeAttribute(source)}" alt="${escapeAttribute(item.name || `image-${index + 1}`)}">`;
} else if (item.mimeType.startsWith('video/')) {
html += `<video controls muted playsinline preload="metadata" src="${escapeAttribute(source)}"></video>`;
}
}
});
return html;
}
// ═══════════════════════════════════════
// 1. 环境检测
// ═══════════════════════════════════════
@ -459,7 +546,24 @@ function checkBridge() {
log('err', 'Bridge', 'window.AppShell 未定义');
return;
}
const methods = ['pickImage','captureImage','pickFile','openExternal','requestPermissions','reloadPage','goBack','closeApp','getDeviceInfo','getNetworkStatus','showToast','setStatusBar'];
const methods = [
'pickImage',
'captureImage',
'pickVideo',
'captureVideo',
'pickFile',
'openExternal',
'requestPermissions',
'reloadPage',
'reloadUpgradeRuntimeConfig',
'reloadUpgradeRuntimeConfigAndCheckVersion',
'goBack',
'closeApp',
'getDeviceInfo',
'getNetworkStatus',
'showToast',
'setStatusBar',
];
const available = methods.filter(m => typeof shell[m] === 'function');
const missing = methods.filter(m => typeof shell[m] !== 'function');
@ -544,18 +648,16 @@ async function testPickImage(multiple) {
log('info', 'pickImage', `调用 pickImage({multiple: ${multiple}})…`);
try {
const result = await AppShell.pickImage({ multiple, responseType: 'dataUrl' });
if (result == null || (Array.isArray(result) && result.length === 0)) {
const items = normalizeBridgeItems(result);
if (items.length === 0) {
setPreview('pickImagePreview', '⚠️ 用户取消(' + label + '');
log('warn', 'pickImage', '用户取消');
return;
}
const items = Array.isArray(result) ? result : [result];
let html = `<b>${label} - 共 ${items.length} 张:</b><br>`;
items.forEach((img, i) => {
html += `${i + 1}. ${img.name || '-'} (${img.mimeType || '-'})<br>`;
if (img.dataUrl) html += `<img src="${img.dataUrl}" alt="选图${i + 1}">`;
});
setPreview('pickImagePreview', html);
setPreview(
'pickImagePreview',
buildBridgeMediaPreviewHtml(`${label} - 共 ${items.length} 张`, items),
);
log('ok', 'pickImage', { mode: label, count: items.length });
} catch (e) {
setPreview('pickImagePreview', '❌ 错误: ' + e.message);
@ -564,28 +666,83 @@ async function testPickImage(multiple) {
}
// ═══════════════════════════════════════
// 5. pickFile
// 5. captureVideo
// ═══════════════════════════════════════
async function testCaptureVideo() {
if (!window.AppShell) { log('err', 'captureVideo', 'AppShell 不可用'); return; }
log('info', 'captureVideo', "调用 captureVideo({responseType: 'uri'})…");
try {
const result = await AppShell.captureVideo({ responseType: 'uri' });
const items = normalizeBridgeItems(result);
if (items.length === 0) {
setPreview('captureVideoPreview', '⚠️ 用户取消了录像');
log('warn', 'captureVideo', '用户取消');
return;
}
setPreview(
'captureVideoPreview',
buildBridgeMediaPreviewHtml('录像结果', items),
);
log('ok', 'captureVideo', {
name: items[0].name,
mimeType: items[0].mimeType,
size: items[0].size,
});
} catch (e) {
setPreview('captureVideoPreview', '❌ 错误: ' + e.message);
log('err', 'captureVideo', e.message);
}
}
// ═══════════════════════════════════════
// 6. pickVideo
// ═══════════════════════════════════════
async function testPickVideo(multiple) {
if (!window.AppShell) { log('err', 'pickVideo', 'AppShell 不可用'); return; }
const label = multiple ? '多选' : '单选';
log('info', 'pickVideo', `调用 pickVideo({multiple: ${multiple}, responseType: 'uri'})…`);
try {
const result = await AppShell.pickVideo({ multiple, responseType: 'uri' });
const items = normalizeBridgeItems(result);
if (items.length === 0) {
setPreview('pickVideoPreview', '⚠️ 用户取消(' + label + '');
log('warn', 'pickVideo', '用户取消');
return;
}
setPreview(
'pickVideoPreview',
buildBridgeMediaPreviewHtml(`${label} - 共 ${items.length} 个视频`, items),
);
log('ok', 'pickVideo', { mode: label, count: items.length });
} catch (e) {
setPreview('pickVideoPreview', '❌ 错误: ' + e.message);
log('err', 'pickVideo', e.message);
}
}
// ═══════════════════════════════════════
// 7. pickFile
// ═══════════════════════════════════════
async function testPickFile(multiple, responseType) {
return testPickFileWithOptions({ multiple, responseType }, multiple ? '任意多选' : '任意单选');
}
async function testPickFileWithOptions(options, label) {
if (!window.AppShell) { log('err', 'pickFile', 'AppShell 不可用'); return; }
log('info', 'pickFile', `调用 pickFile({multiple: ${multiple}, responseType: '${responseType}'})…`);
log('info', 'pickFile', `调用 pickFile(${JSON.stringify(options)}) [${label}]…`);
try {
const result = await AppShell.pickFile({ multiple, responseType });
if (result == null || (Array.isArray(result) && result.length === 0)) {
const result = await AppShell.pickFile(options);
const items = normalizeBridgeItems(result);
if (items.length === 0) {
setPreview('pickFilePreview', '⚠️ 用户取消');
log('warn', 'pickFile', '用户取消');
return;
}
const items = Array.isArray(result) ? result : [result];
let html = `<b>共 ${items.length} 个文件:</b><br>`;
items.forEach((f, i) => {
html += `${i + 1}. <b>${f.name || '-'}</b> | ${f.mimeType || '-'} | ${f.size || '-'} bytes | uri: ${f.uri || '-'}`;
if (f.dataUrl) html += ' | dataUrl: ✅';
if (f.base64) html += ' | base64: ✅ (' + f.base64.length + ' chars)';
html += '<br>';
});
setPreview('pickFilePreview', html);
log('ok', 'pickFile', { count: items.length, responseType });
setPreview(
'pickFilePreview',
buildBridgeMediaPreviewHtml(`${label} - 共 ${items.length} 个文件`, items),
);
log('ok', 'pickFile', { label, count: items.length, options });
} catch (e) {
setPreview('pickFilePreview', '❌ 错误: ' + e.message);
log('err', 'pickFile', e.message);
@ -593,7 +750,7 @@ async function testPickFile(multiple, responseType) {
}
// ═══════════════════════════════════════
// 6. openExternal
// 8. openExternal
// ═══════════════════════════════════════
async function testOpenExternal(url) {
if (!window.AppShell) { log('err', 'openExternal', 'AppShell 不可用'); return; }
@ -610,7 +767,7 @@ async function testOpenExternal(url) {
}
// ═══════════════════════════════════════
// 7. requestPermissions
// 9. requestPermissions
// ═══════════════════════════════════════
async function testPermissions(types) {
if (!window.AppShell) { log('err', 'Permissions', 'AppShell 不可用'); return; }
@ -637,7 +794,7 @@ async function testPermissions(types) {
}
// ═══════════════════════════════════════
// 8. 页面控制
// 10. 页面控制
// ═══════════════════════════════════════
async function testReload() {
if (!window.AppShell) { log('err', 'Control', 'AppShell 不可用'); return; }
@ -668,7 +825,48 @@ async function testCloseApp() {
}
// ═══════════════════════════════════════
// 8.58.8 Phase 2 新增能力
// 10.5 运行时配置
// ═══════════════════════════════════════
async function testReloadUpgradeRuntimeConfig() {
if (!window.AppShell) { log('err', 'RuntimeConfig', 'AppShell 不可用'); return; }
log('info', 'RuntimeConfig', '调用 reloadUpgradeRuntimeConfig()…');
try {
const result = await AppShell.reloadUpgradeRuntimeConfig();
setPreview(
'runtimeConfigPreview',
'<b>当前运行时配置快照:</b><br>' + escapeHtml(JSON.stringify(result, null, 2)).replace(/\n/g, '<br>'),
);
log('ok', 'RuntimeConfig', result);
} catch (e) {
setPreview('runtimeConfigPreview', '❌ 错误: ' + e.message);
log('err', 'RuntimeConfig', e.message);
}
}
async function testReloadUpgradeRuntimeConfigAndCheckVersion(showNoUpdateToast) {
if (!window.AppShell) { log('err', 'RuntimeConfig', 'AppShell 不可用'); return; }
log(
'info',
'RuntimeConfig',
`调用 reloadUpgradeRuntimeConfigAndCheckVersion({showNoUpdateToast: ${showNoUpdateToast}})…`,
);
try {
const result = await AppShell.reloadUpgradeRuntimeConfigAndCheckVersion({
showNoUpdateToast,
});
setPreview(
'runtimeConfigPreview',
'<b>重载并检查升级后的配置快照:</b><br>' + escapeHtml(JSON.stringify(result, null, 2)).replace(/\n/g, '<br>'),
);
log('ok', 'RuntimeConfig', result);
} catch (e) {
setPreview('runtimeConfigPreview', '❌ 错误: ' + e.message);
log('err', 'RuntimeConfig', e.message);
}
}
// ═══════════════════════════════════════
// 1114 Phase 2 新增能力
// ═══════════════════════════════════════
async function testGetDeviceInfo() {
if (!window.AppShell) { log('err', 'DeviceInfo', 'AppShell 不可用'); return; }