feat: add Flutter web build support

This commit is contained in:
2026-08-02 01:30:07 +08:00
parent 98bf7ed6a9
commit f0b8af0bc8
24 changed files with 708 additions and 329 deletions

View File

@@ -1,6 +1,6 @@
# 瓶安芯用户端
Android/iOS Flutter 客户端。首期只接入 `/heqi/client/v1/user` 的真实能力:首页安全内容与服务归属、商城、订单、合同、工单、钱包、地址和个人资料。
Android/iOS/Web Flutter 客户端。首期只接入 `/heqi/client/v1/user` 的真实能力:首页安全内容与服务归属、商城、订单、合同、工单、钱包、地址和个人资料。
## 本地运行
@@ -18,6 +18,9 @@ flutter analyze
flutter test
flutter build apk --debug
flutter build ios --simulator --no-codesign
flutter build web --release --dart-define=API_BASE_URL=https://api.example.com
```
仓库根目录可使用 `API_BASE_URL=https://api.example.com ./scripts/build-apps.sh user_app all` 同时生成 Android 和 Web 产物。Web 本地调试使用 `flutter run -d chrome --dart-define=API_BASE_URL=http://127.0.0.1:12426`;生产环境必须使用 HTTPS API 地址。
充值 Mock 确认、设备控制、收藏、押金、消息和发票均不在 Release UI 暴露。

View File

@@ -1,5 +1,4 @@
import 'dart:convert';
import 'dart:io';
import 'package:http/http.dart' as http;
@@ -51,13 +50,13 @@ class ApiClient {
bool authenticated = true,
}) async {
final request = http.Request(method, Uri.parse('$baseUrl$path'));
request.headers[HttpHeaders.acceptHeader] = 'application/json';
request.headers['accept'] = 'application/json';
if (authenticated) {
final token = _tokenProvider();
if (token.isNotEmpty) request.headers[HttpHeaders.authorizationHeader] = token;
if (token.isNotEmpty) request.headers['authorization'] = token;
}
if (body != null) {
request.headers[HttpHeaders.contentTypeHeader] = 'application/json; charset=UTF-8';
request.headers['content-type'] = 'application/json; charset=UTF-8';
request.body = jsonEncode(body);
}
final streamed = await _client.send(request);

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64"><rect width="64" height="64" rx="14" fill="#00695c"/><path d="M32 11c10 8 16 16 16 25a16 16 0 1 1-32 0c0-9 6-17 16-25Z" fill="#fff"/><path d="M25 38h14" stroke="#00695c" stroke-width="4" stroke-linecap="round"/></svg>

After

Width:  |  Height:  |  Size: 278 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><rect width="512" height="512" rx="112" fill="#00695c"/><path d="M256 88c80 65 128 130 128 204a128 128 0 1 1-256 0c0-74 48-139 128-204Z" fill="#fff"/><path d="M200 310h112" stroke="#00695c" stroke-width="34" stroke-linecap="round"/></svg>

After

Width:  |  Height:  |  Size: 301 B

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<base href="$FLUTTER_BASE_HREF">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="和气瓶安用户端 Web 应用。">
<meta name="theme-color" content="#00695c">
<link rel="icon" href="favicon.svg" type="image/svg+xml">
<link rel="manifest" href="manifest.json">
<title>和气瓶安</title>
</head>
<body>
<script src="flutter_bootstrap.js" async></script>
</body>
</html>

View File

@@ -0,0 +1,17 @@
{
"name": "和气瓶安",
"short_name": "和气瓶安",
"start_url": ".",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#00695c",
"description": "和气瓶安用户端 Web 应用。",
"icons": [
{
"src": "icons/app-icon.svg",
"sizes": "any",
"type": "image/svg+xml",
"purpose": "any maskable"
}
]
}