fix: 欢迎卡片UI优化 + 蓝牙录入按钮 + 多处修复
- 欢迎卡片:去掉白框圆角错位、图片满宽、按钮去箭头改圆角居中 - 渐变actionOutlineGradient改紫蓝双色循环 - 新增健康Agent"蓝牙录入"按钮→蓝牙设备页 - "查看健康情况"改名"健康概览" - 饮食编辑框删除bug修复(控制器缓存) - 启动脚本加adb reverse自动转发 - 登录闪屏修复
This commit is contained in:
@@ -27,7 +27,15 @@ class ChatMessage {
|
||||
bool get isUser => role == 'user';
|
||||
}
|
||||
|
||||
enum ActiveAgent { default_, consultation, health, diet, medication, report, exercise }
|
||||
enum ActiveAgent {
|
||||
default_,
|
||||
consultation,
|
||||
health,
|
||||
diet,
|
||||
medication,
|
||||
report,
|
||||
exercise,
|
||||
}
|
||||
|
||||
class ChatState {
|
||||
final ActiveAgent activeAgent;
|
||||
@@ -42,15 +50,19 @@ class ChatState {
|
||||
this.isStreaming = false,
|
||||
this.thinkingText,
|
||||
});
|
||||
ChatState copyWith({ActiveAgent? activeAgent, List<ChatMessage>? messages,
|
||||
String? conversationId, bool? isStreaming, String? thinkingText}) =>
|
||||
ChatState(
|
||||
activeAgent: activeAgent ?? this.activeAgent,
|
||||
messages: messages ?? this.messages,
|
||||
conversationId: conversationId ?? this.conversationId,
|
||||
isStreaming: isStreaming ?? this.isStreaming,
|
||||
thinkingText: thinkingText ?? this.thinkingText,
|
||||
);
|
||||
ChatState copyWith({
|
||||
ActiveAgent? activeAgent,
|
||||
List<ChatMessage>? messages,
|
||||
String? conversationId,
|
||||
bool? isStreaming,
|
||||
String? thinkingText,
|
||||
}) => ChatState(
|
||||
activeAgent: activeAgent ?? this.activeAgent,
|
||||
messages: messages ?? this.messages,
|
||||
conversationId: conversationId ?? this.conversationId,
|
||||
isStreaming: isStreaming ?? this.isStreaming,
|
||||
thinkingText: thinkingText ?? this.thinkingText,
|
||||
);
|
||||
}
|
||||
|
||||
class SelectedAgentNotifier extends Notifier<ActiveAgent?> {
|
||||
@@ -60,18 +72,29 @@ class SelectedAgentNotifier extends Notifier<ActiveAgent?> {
|
||||
}
|
||||
|
||||
final selectedAgentProvider =
|
||||
NotifierProvider<SelectedAgentNotifier, ActiveAgent?>(SelectedAgentNotifier.new);
|
||||
final chatProvider = NotifierProvider<ChatNotifier, ChatState>(ChatNotifier.new);
|
||||
NotifierProvider<SelectedAgentNotifier, ActiveAgent?>(
|
||||
SelectedAgentNotifier.new,
|
||||
);
|
||||
final chatProvider = NotifierProvider<ChatNotifier, ChatState>(
|
||||
ChatNotifier.new,
|
||||
);
|
||||
|
||||
ActiveAgent _parseAgent(String? type) {
|
||||
switch (type?.toLowerCase()) {
|
||||
case 'consultation': return ActiveAgent.consultation;
|
||||
case 'health': return ActiveAgent.health;
|
||||
case 'diet': return ActiveAgent.diet;
|
||||
case 'medication': return ActiveAgent.medication;
|
||||
case 'report': return ActiveAgent.report;
|
||||
case 'exercise': return ActiveAgent.exercise;
|
||||
default: return ActiveAgent.default_;
|
||||
case 'consultation':
|
||||
return ActiveAgent.consultation;
|
||||
case 'health':
|
||||
return ActiveAgent.health;
|
||||
case 'diet':
|
||||
return ActiveAgent.diet;
|
||||
case 'medication':
|
||||
return ActiveAgent.medication;
|
||||
case 'report':
|
||||
return ActiveAgent.report;
|
||||
case 'exercise':
|
||||
return ActiveAgent.exercise;
|
||||
default:
|
||||
return ActiveAgent.default_;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +108,10 @@ class ChatNotifier extends Notifier<ChatState> {
|
||||
void confirmMessage(String id) {
|
||||
final msgs = state.messages.toList();
|
||||
final i = msgs.indexWhere((m) => m.id == id);
|
||||
if (i >= 0) { msgs[i].confirmed = true; state = state.copyWith(messages: msgs); }
|
||||
if (i >= 0) {
|
||||
msgs[i].confirmed = true;
|
||||
state = state.copyWith(messages: msgs);
|
||||
}
|
||||
ref.invalidate(medicationListProvider);
|
||||
ref.invalidate(latestHealthProvider);
|
||||
}
|
||||
@@ -93,7 +119,10 @@ class ChatNotifier extends Notifier<ChatState> {
|
||||
void startEditingField(String msgId, String fieldLabel) {
|
||||
final msgs = state.messages.toList();
|
||||
final i = msgs.indexWhere((m) => m.id == msgId);
|
||||
if (i >= 0) { msgs[i].metadata?['_editingField'] = fieldLabel; state = state.copyWith(messages: msgs); }
|
||||
if (i >= 0) {
|
||||
msgs[i].metadata?['_editingField'] = fieldLabel;
|
||||
state = state.copyWith(messages: msgs);
|
||||
}
|
||||
}
|
||||
|
||||
void finishEditingField(String msgId, String fieldLabel, String value) {
|
||||
@@ -116,13 +145,18 @@ class ChatNotifier extends Notifier<ChatState> {
|
||||
|
||||
void insertTaskCard() {
|
||||
if (state.messages.any((m) => m.type == MessageType.taskCard)) return;
|
||||
state = state.copyWith(messages: [ChatMessage(
|
||||
id: 'task_card',
|
||||
role: 'assistant',
|
||||
content: '',
|
||||
createdAt: DateTime.now(),
|
||||
type: MessageType.taskCard,
|
||||
), ...state.messages]);
|
||||
state = state.copyWith(
|
||||
messages: [
|
||||
ChatMessage(
|
||||
id: 'task_card',
|
||||
role: 'assistant',
|
||||
content: '',
|
||||
createdAt: DateTime.now(),
|
||||
type: MessageType.taskCard,
|
||||
),
|
||||
...state.messages,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
void setAgent(ActiveAgent a) {
|
||||
@@ -175,7 +209,9 @@ class ChatNotifier extends Notifier<ChatState> {
|
||||
id: map['id']?.toString() ?? '',
|
||||
role: map['role']?.toString() ?? 'user',
|
||||
content: map['content']?.toString() ?? '',
|
||||
createdAt: DateTime.tryParse(map['createdAt']?.toString() ?? '') ?? DateTime.now(),
|
||||
createdAt:
|
||||
DateTime.tryParse(map['createdAt']?.toString() ?? '') ??
|
||||
DateTime.now(),
|
||||
type: MessageType.text,
|
||||
);
|
||||
}).toList();
|
||||
@@ -190,14 +226,19 @@ class ChatNotifier extends Notifier<ChatState> {
|
||||
}
|
||||
|
||||
void insertAgentWelcome(ActiveAgent agent) {
|
||||
state = state.copyWith(messages: [...state.messages, ChatMessage(
|
||||
id: 'welcome_${agent.name}_${DateTime.now().millisecondsSinceEpoch}',
|
||||
role: 'assistant',
|
||||
content: '',
|
||||
createdAt: DateTime.now(),
|
||||
type: MessageType.agentWelcome,
|
||||
metadata: {'agent': agent.name},
|
||||
)]);
|
||||
state = state.copyWith(
|
||||
messages: [
|
||||
...state.messages,
|
||||
ChatMessage(
|
||||
id: 'welcome_${agent.name}_${DateTime.now().millisecondsSinceEpoch}',
|
||||
role: 'assistant',
|
||||
content: '',
|
||||
createdAt: DateTime.now(),
|
||||
type: MessageType.agentWelcome,
|
||||
metadata: {'agent': agent.name},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/// 点击胶囊:先出用户标签 → 0.4 秒后出欢迎卡片,不走 AI
|
||||
@@ -275,7 +316,9 @@ class ChatNotifier extends Notifier<ChatState> {
|
||||
createdAt: DateTime.now(),
|
||||
);
|
||||
state = state.copyWith(
|
||||
messages: [...state.messages, userMsg], isStreaming: true);
|
||||
messages: [...state.messages, userMsg],
|
||||
isStreaming: true,
|
||||
);
|
||||
|
||||
await _sendToAI(text);
|
||||
}
|
||||
@@ -289,7 +332,10 @@ class ChatNotifier extends Notifier<ChatState> {
|
||||
);
|
||||
|
||||
// 立即加入空 AI 消息,让思考动画有载体
|
||||
state = state.copyWith(messages: [...state.messages, aiMsg], isStreaming: true);
|
||||
state = state.copyWith(
|
||||
messages: [...state.messages, aiMsg],
|
||||
isStreaming: true,
|
||||
);
|
||||
|
||||
try {
|
||||
final token = await ref.read(apiClientProvider).accessToken;
|
||||
@@ -309,25 +355,25 @@ class ChatNotifier extends Notifier<ChatState> {
|
||||
await for (final event in stream) {
|
||||
_processEvent(event, aiMsg);
|
||||
}
|
||||
if (state.isStreaming) {
|
||||
_done(aiMsg);
|
||||
}
|
||||
} catch (e) {
|
||||
_addError(aiMsg, '网络异常,请稍后重试');
|
||||
}
|
||||
}
|
||||
|
||||
void _addError(ChatMessage aiMsg, String errorText) {
|
||||
state = state.copyWith(
|
||||
messages: [
|
||||
...state.messages,
|
||||
ChatMessage(
|
||||
id: 'err_${DateTime.now().millisecondsSinceEpoch}',
|
||||
role: 'assistant',
|
||||
content: errorText,
|
||||
createdAt: DateTime.now(),
|
||||
),
|
||||
],
|
||||
isStreaming: false,
|
||||
thinkingText: null,
|
||||
);
|
||||
aiMsg.content = errorText;
|
||||
aiMsg.type = MessageType.text;
|
||||
final u = state.messages.toList();
|
||||
final i = u.indexWhere((x) => x.id == aiMsg.id);
|
||||
if (i >= 0) {
|
||||
u[i] = aiMsg;
|
||||
} else {
|
||||
u.add(aiMsg);
|
||||
}
|
||||
state = state.copyWith(messages: u, isStreaming: false, thinkingText: null);
|
||||
}
|
||||
|
||||
void _processEvent(Map<String, dynamic> j, ChatMessage aiMsg) {
|
||||
@@ -385,7 +431,16 @@ class ChatNotifier extends Notifier<ChatState> {
|
||||
|
||||
void _done(ChatMessage m) {
|
||||
final u = state.messages.toList();
|
||||
if (!u.any((x) => x.id == m.id) && m.content.isNotEmpty) u.add(m);
|
||||
final content = m.content.trim();
|
||||
if (content.isEmpty && m.type == MessageType.text) {
|
||||
m.content = '暂时没有收到回复,请稍后再试。';
|
||||
}
|
||||
final i = u.indexWhere((x) => x.id == m.id);
|
||||
if (i >= 0) {
|
||||
u[i] = m;
|
||||
} else {
|
||||
u.add(m);
|
||||
}
|
||||
state = state.copyWith(messages: u, isStreaming: false, thinkingText: null);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user