feat: harden ai onboarding and approval chat flows

This commit is contained in:
kris
2026-03-31 04:18:57 +08:00
parent 4336dc22a7
commit 0cb2171dd3
16 changed files with 551 additions and 27 deletions

View File

@@ -306,27 +306,17 @@ public class AiAccountsActivity extends BossScreenActivity {
BossApiClient.ApiResponse response = apiClient.onboardOpenAiApiAccount(payload);
if (!response.ok()) throw new IllegalStateException(response.message());
String accountId = extractAccountId(response.json);
if (accountId.isEmpty()) {
runOnUiThread(() -> {
showMessage("OpenAI 平台账号已登录,并设为当前主控。");
reload();
});
return;
}
BossApiClient.ApiResponse validation = apiClient.validateAccount(accountId);
runOnUiThread(() -> {
showMessage(validation.ok()
? validation.message()
: "登录完成,但校验失败:" + validation.message());
showMessage("OpenAI 平台账号已登录,并设为当前主控。");
reload();
});
} catch (Exception error) {
runOnUiThread(() -> {
setRefreshing(false);
showMessage("登录失败:" + error.getMessage());
String detail = error.getMessage();
showMessage(detail == null || detail.trim().isEmpty()
? "OpenAI 平台账号登录失败,请稍后重试。"
: "OpenAI 平台账号登录失败:" + detail);
});
}
});

View File

@@ -111,10 +111,12 @@ public class ProjectDetailActivity extends BossScreenActivity {
private static final class ProjectSnapshot {
final JSONObject payload;
final @Nullable JSONArray dispatchPlans;
final @Nullable JSONObject participantsPayload;
ProjectSnapshot(JSONObject payload, @Nullable JSONArray dispatchPlans) {
ProjectSnapshot(JSONObject payload, @Nullable JSONArray dispatchPlans, @Nullable JSONObject participantsPayload) {
this.payload = payload;
this.dispatchPlans = dispatchPlans;
this.participantsPayload = participantsPayload;
}
}
@@ -228,7 +230,7 @@ public class ProjectDetailActivity extends BossScreenActivity {
executor.execute(() -> {
try {
ProjectSnapshot snapshot = fetchProjectSnapshot();
runOnUiThread(() -> renderProject(snapshot.payload, snapshot.dispatchPlans));
runOnUiThread(() -> renderProject(snapshot.payload, snapshot.dispatchPlans, snapshot.participantsPayload));
} catch (Exception error) {
runOnUiThread(() -> {
setRefreshing(false);
@@ -257,7 +259,11 @@ public class ProjectDetailActivity extends BossScreenActivity {
updateSelectionUi();
}
private void renderProject(JSONObject payload, @Nullable JSONArray dispatchPlans) {
private void renderProject(
JSONObject payload,
@Nullable JSONArray dispatchPlans,
@Nullable JSONObject participantsPayload
) {
JSONObject project = payload.optJSONObject("project");
JSONArray devices = payload.optJSONArray("devices");
JSONObject threadMeta = project == null ? null : project.optJSONObject("threadMeta");
@@ -278,6 +284,9 @@ public class ProjectDetailActivity extends BossScreenActivity {
if (currentPendingDispatchPlan != null) {
appendContent(buildPendingDispatchPlanView(currentPendingDispatchPlan));
}
if (projectIsGroup && participantsPayload != null && participantsPayload.optBoolean("repairRequired", false)) {
appendContent(buildRepairGroupMembersView(participantsPayload));
}
JSONArray messages = project == null ? null : project.optJSONArray("messages");
selectionState = ProjectChatUiState.reconcileSelection(selectionState, collectMessageIds(messages));
@@ -585,7 +594,29 @@ public class ProjectDetailActivity extends BossScreenActivity {
));
Button confirmButton = BossUi.buildMiniActionButton(this, "确认下发", true);
confirmButton.setOnClickListener(v -> showDispatchPlanConfirmation(dispatchPlan));
container.addView(BossUi.buildInlineActionRow(this, confirmButton));
Button rejectButton = BossUi.buildMiniActionButton(this, "拒绝", false);
rejectButton.setOnClickListener(v -> rejectDispatchPlan(dispatchPlan));
container.addView(BossUi.buildInlineActionRow(this, confirmButton, rejectButton));
return container;
}
private View buildRepairGroupMembersView(JSONObject participantsPayload) {
String repairReason = participantsPayload.optString("repairReason", "当前群聊里有失效线程,请先修复群成员。");
int invalidParticipantCount = participantsPayload.optInt("invalidParticipantCount", 0);
String meta = invalidParticipantCount > 0
? "存在 " + invalidParticipantCount + " 个失效成员"
: "当前群聊还没有可下发的真实线程";
LinearLayout container = new LinearLayout(this);
container.setOrientation(LinearLayout.VERTICAL);
container.addView(BossUi.buildCard(
this,
"修复群成员",
repairReason,
meta
));
Button repairButton = BossUi.buildMiniActionButton(this, "去修复", true);
repairButton.setOnClickListener(v -> openConversationInfo());
container.addView(BossUi.buildInlineActionRow(this, repairButton));
return container;
}
@@ -1532,6 +1563,7 @@ public class ProjectDetailActivity extends BossScreenActivity {
throw new IllegalStateException(detailResponse.message());
}
JSONArray dispatchPlans = null;
JSONObject participantsPayload = null;
if (includeDispatchPlans) {
try {
BossApiClient.ApiResponse dispatchPlansResponse = apiClient.getDispatchPlans(projectId);
@@ -1541,8 +1573,16 @@ public class ProjectDetailActivity extends BossScreenActivity {
} catch (Exception ignored) {
dispatchPlans = null;
}
try {
BossApiClient.ApiResponse participantsResponse = apiClient.getConversationParticipants(projectId);
if (participantsResponse.ok()) {
participantsPayload = participantsResponse.json;
}
} catch (Exception ignored) {
participantsPayload = null;
}
}
return new ProjectSnapshot(detailResponse.json, dispatchPlans);
return new ProjectSnapshot(detailResponse.json, dispatchPlans, participantsPayload);
}
private void startReplyWait(
@@ -1571,7 +1611,7 @@ public class ProjectDetailActivity extends BossScreenActivity {
if (!renderedInitialSnapshot || hasReply) {
runOnUiThread(() -> {
renderProject(snapshot.payload, snapshot.dispatchPlans);
renderProject(snapshot.payload, snapshot.dispatchPlans, snapshot.participantsPayload);
if (!hasReply) {
composerSending = true;
updateComposerSendButtonState();