修正上架時 Google Play 檢查出的 issue
This commit is contained in:
@@ -14,12 +14,12 @@ class PersonApiService {
|
||||
filterPart = "personcname^%$searchName%";
|
||||
}
|
||||
|
||||
String v_queryFilter = "1^100^personid^*^^^$filterPart";
|
||||
String vQueryfilter = "1^100^personid^*^^^$filterPart";
|
||||
|
||||
return await _apiService.fetchList<Person>(
|
||||
tableName: "basperson", // 對應到 basperson 表格
|
||||
pk: "personid", // 主鍵為 personid
|
||||
queryFilter: v_queryFilter,
|
||||
queryFilter: vQueryfilter,
|
||||
fromJson: (json) => Person.fromJson(json),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
// 1. 必須加入這一行,否則系統不認識 launchUrl
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
import './person_model.dart';
|
||||
import 'package:url_launcher/url_launcher.dart'; // 用於撥打電話和發送郵件
|
||||
|
||||
class PersonDetail extends StatelessWidget {
|
||||
final Person person;
|
||||
@@ -18,10 +19,10 @@ class PersonDetail extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
// 姓名與職稱
|
||||
CircleAvatar(
|
||||
radius: 50,
|
||||
backgroundColor: person.sexColor.withOpacity(0.2),
|
||||
// 修正 .withOpacity 警告,改用新的 .withValues
|
||||
backgroundColor: person.sexColor.withValues(alpha: 0.2),
|
||||
child: Icon(person.sexIcon, size: 60, color: person.sexColor),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
@@ -35,48 +36,17 @@ class PersonDetail extends StatelessWidget {
|
||||
),
|
||||
const Divider(height: 30.0, thickness: 1),
|
||||
|
||||
// 聯絡資訊列表
|
||||
_buildInfoTile(
|
||||
Icons.badge,
|
||||
'工號 / ID',
|
||||
person.personId,
|
||||
),
|
||||
_buildInfoTile(
|
||||
Icons.business,
|
||||
'部門代號',
|
||||
person.departmentId ?? 'N/A',
|
||||
),
|
||||
_buildActionTile(
|
||||
context,
|
||||
Icons.phone,
|
||||
'公司電話',
|
||||
person.tel ?? 'N/A',
|
||||
person.tel,
|
||||
'tel:',
|
||||
),
|
||||
_buildActionTile(
|
||||
context,
|
||||
Icons.smartphone,
|
||||
'手機號碼',
|
||||
person.cellphone ?? 'N/A',
|
||||
person.cellphone,
|
||||
'tel:',
|
||||
),
|
||||
_buildActionTile(
|
||||
context,
|
||||
Icons.email,
|
||||
'電子郵件',
|
||||
person.email ?? 'N/A',
|
||||
person.email,
|
||||
'mailto:',
|
||||
),
|
||||
_buildInfoTile(Icons.badge, '工號 / ID', person.personId),
|
||||
_buildInfoTile(Icons.business, '部門代號', person.departmentId ?? 'N/A'),
|
||||
_buildActionTile(context, Icons.phone, '公司電話', person.tel ?? 'N/A', person.tel, 'tel:'),
|
||||
_buildActionTile(context, Icons.smartphone, '手機號碼', person.cellphone ?? 'N/A', person.cellphone, 'tel:'),
|
||||
_buildActionTile(context, Icons.email, '電子郵件', person.email ?? 'N/A', person.email, 'mailto:'),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 靜態資訊欄位
|
||||
Widget _buildInfoTile(IconData icon, String label, String value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
@@ -88,14 +58,8 @@ class PersonDetail extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: const TextStyle(fontSize: 14, color: Colors.grey),
|
||||
),
|
||||
Text(
|
||||
value,
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
|
||||
),
|
||||
Text(label, style: const TextStyle(fontSize: 14, color: Colors.grey)),
|
||||
Text(value, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -104,19 +68,29 @@ class PersonDetail extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
// 可操作(點擊撥號/發送郵件)的欄位
|
||||
Widget _buildActionTile(
|
||||
BuildContext context, IconData icon, String label, String displayValue,
|
||||
String? actionValue, String protocol) {
|
||||
final canLaunch = actionValue != null && actionValue.isNotEmpty;
|
||||
|
||||
Future<void> _launchUrl() async {
|
||||
// 修正點:在 StatelessWidget 中我們不使用 mounted,直接處理即可
|
||||
Future<void> _handleLaunch() async {
|
||||
if (canLaunch) {
|
||||
final uri = Uri.parse('$protocol$actionValue');
|
||||
if (!await launchUrl(uri)) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('無法打開 $displayValue')),
|
||||
);
|
||||
final Uri uri = Uri.parse('$protocol$actionValue');
|
||||
try {
|
||||
if (!await launchUrl(uri)) {
|
||||
if (context.mounted) { // 修正點:StatelessWidget 要用 context.mounted
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('無法打開 $displayValue')),
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('執行錯誤: $e')),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,7 +98,7 @@ class PersonDetail extends StatelessWidget {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: InkWell(
|
||||
onTap: canLaunch ? _launchUrl : null,
|
||||
onTap: canLaunch ? _handleLaunch : null,
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, color: canLaunch ? Colors.deepPurple : Colors.grey[700], size: 24),
|
||||
@@ -133,10 +107,7 @@ class PersonDetail extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: const TextStyle(fontSize: 14, color: Colors.grey),
|
||||
),
|
||||
Text(label, style: const TextStyle(fontSize: 14, color: Colors.grey)),
|
||||
Text(
|
||||
displayValue,
|
||||
style: TextStyle(
|
||||
|
||||
Reference in New Issue
Block a user