feat: queue device import review tasks
This commit is contained in:
@@ -23,7 +23,9 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
private String deviceName;
|
||||
private @Nullable JSONObject currentDraft;
|
||||
private @Nullable JSONObject currentResolution;
|
||||
private @Nullable JSONObject currentReviewTask;
|
||||
private final LinkedHashSet<String> selectedCandidateIds = new LinkedHashSet<>();
|
||||
private final Runnable reviewPollRunnable = this::reload;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -48,7 +50,11 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
if (!response.ok()) {
|
||||
throw new IllegalStateException(response.message());
|
||||
}
|
||||
runOnUiThread(() -> applyPayload(response.json.optJSONObject("draft"), response.json.optJSONObject("resolution")));
|
||||
runOnUiThread(() -> applyPayload(
|
||||
response.json.optJSONObject("draft"),
|
||||
response.json.optJSONObject("resolution"),
|
||||
response.json.optJSONObject("reviewTask")
|
||||
));
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> {
|
||||
setRefreshing(false);
|
||||
@@ -58,9 +64,10 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private void applyPayload(@Nullable JSONObject draft, @Nullable JSONObject resolution) {
|
||||
private void applyPayload(@Nullable JSONObject draft, @Nullable JSONObject resolution, @Nullable JSONObject reviewTask) {
|
||||
currentDraft = draft;
|
||||
currentResolution = resolution;
|
||||
currentReviewTask = reviewTask;
|
||||
selectedCandidateIds.clear();
|
||||
JSONArray selected = draft == null ? null : draft.optJSONArray("selectedCandidateIds");
|
||||
if (selected != null) {
|
||||
@@ -74,9 +81,31 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
renderCurrentState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
contentLayout.removeCallbacks(reviewPollRunnable);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
private boolean isReviewPending(@Nullable JSONObject draft, @Nullable JSONObject resolution, @Nullable JSONObject reviewTask) {
|
||||
if (draft == null || resolution != null) {
|
||||
return false;
|
||||
}
|
||||
if (!"pending_resolution".equals(draft.optString("status", ""))) {
|
||||
return false;
|
||||
}
|
||||
if (reviewTask == null) {
|
||||
return false;
|
||||
}
|
||||
String taskStatus = reviewTask.optString("status", "");
|
||||
return "queued".equals(taskStatus) || "running".equals(taskStatus);
|
||||
}
|
||||
|
||||
private void renderCurrentState() {
|
||||
JSONObject draft = currentDraft;
|
||||
JSONObject resolution = currentResolution;
|
||||
JSONObject reviewTask = currentReviewTask;
|
||||
contentLayout.removeCallbacks(reviewPollRunnable);
|
||||
replaceContent();
|
||||
appendContent(BossUi.buildSoftPanel(
|
||||
this,
|
||||
@@ -110,7 +139,7 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
appendContent(BossUi.buildCard(
|
||||
this,
|
||||
resolveStatusTitle(draft),
|
||||
resolveStatusBody(draft, resolution),
|
||||
resolveStatusBody(draft, resolution, reviewTask),
|
||||
"候选 " + candidates.length()
|
||||
+ " · 已选 " + selectedCandidateIds.size()
|
||||
+ " · 推荐 " + recommendedCount
|
||||
@@ -183,6 +212,17 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
}
|
||||
}
|
||||
|
||||
if (reviewTask != null) {
|
||||
appendContent(BossUi.buildCard(
|
||||
this,
|
||||
"审核任务",
|
||||
"状态:" + reviewTask.optString("status", "unknown"),
|
||||
isReviewPending(draft, resolution, reviewTask)
|
||||
? "主 Agent 正在生成导入建议,页面会自动刷新。"
|
||||
: "如果任务失败,可以直接重新生成导入建议。"
|
||||
));
|
||||
}
|
||||
|
||||
JSONArray appliedProjectNames = draft.optJSONArray("appliedProjectNames");
|
||||
if (appliedProjectNames != null && appliedProjectNames.length() > 0) {
|
||||
appendContent(BossUi.buildCard(
|
||||
@@ -194,7 +234,14 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
}
|
||||
|
||||
Button reviewButton = BossUi.buildMiniActionButton(this, "生成导入建议", true);
|
||||
reviewButton.setEnabled(!selectedCandidateIds.isEmpty());
|
||||
reviewButton.setEnabled(!selectedCandidateIds.isEmpty() && !isReviewPending(draft, resolution, reviewTask));
|
||||
if (isReviewPending(draft, resolution, reviewTask)) {
|
||||
reviewButton.setText("主 Agent 审核中");
|
||||
} else if (reviewTask != null && "failed".equals(reviewTask.optString("status", ""))) {
|
||||
reviewButton.setText("重新生成导入建议");
|
||||
} else if ("resolved".equals(draft.optString("status", "")) || "applied".equals(draft.optString("status", ""))) {
|
||||
reviewButton.setText("重新生成导入建议");
|
||||
}
|
||||
reviewButton.setOnClickListener(v -> reviewSelection());
|
||||
Button clearButton = BossUi.buildMiniActionButton(this, "清空勾选", false);
|
||||
clearButton.setEnabled(!selectedCandidateIds.isEmpty());
|
||||
@@ -208,6 +255,9 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
applyButton.setOnClickListener(v -> applyResolution());
|
||||
appendContent(BossUi.buildInlineActionRow(this, reviewButton, clearButton, applyButton));
|
||||
setRefreshing(false);
|
||||
if (isReviewPending(draft, resolution, reviewTask)) {
|
||||
contentLayout.postDelayed(reviewPollRunnable, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveStatusTitle(@Nullable JSONObject draft) {
|
||||
@@ -233,7 +283,7 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
return "导入草稿";
|
||||
}
|
||||
|
||||
private String resolveStatusBody(@Nullable JSONObject draft, @Nullable JSONObject resolution) {
|
||||
private String resolveStatusBody(@Nullable JSONObject draft, @Nullable JSONObject resolution, @Nullable JSONObject reviewTask) {
|
||||
if (draft == null) {
|
||||
return "先让设备完成首次 heartbeat 并上报候选线程,导入草稿就会出现在这里。";
|
||||
}
|
||||
@@ -245,6 +295,12 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
return "先勾选想导入的线程,再生成导入建议。";
|
||||
}
|
||||
if ("pending_resolution".equals(status)) {
|
||||
if (isReviewPending(draft, resolution, reviewTask)) {
|
||||
return "勾选已保存,主 Agent 正在整理导入建议,页面会自动刷新。";
|
||||
}
|
||||
if (reviewTask != null && "failed".equals(reviewTask.optString("status", ""))) {
|
||||
return "主 Agent 这次没能生成导入建议。可以稍后重新生成,当前勾选会保留。";
|
||||
}
|
||||
return "勾选已保存,接下来会生成导入建议。";
|
||||
}
|
||||
if ("resolved".equals(status)) {
|
||||
@@ -306,14 +362,21 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
throw new IllegalStateException(reviewResponse.message());
|
||||
}
|
||||
runOnUiThread(() -> {
|
||||
showMessage("已生成导入建议");
|
||||
applyPayload(reviewResponse.json.optJSONObject("draft"), reviewResponse.json.optJSONObject("resolution"));
|
||||
boolean hasResolution = reviewResponse.json.optJSONObject("resolution") != null;
|
||||
showMessage(hasResolution ? "已生成导入建议" : "已提交给主 Agent 审核");
|
||||
applyPayload(
|
||||
reviewResponse.json.optJSONObject("draft"),
|
||||
reviewResponse.json.optJSONObject("resolution"),
|
||||
reviewResponse.json.optJSONObject("reviewTask") != null
|
||||
? reviewResponse.json.optJSONObject("reviewTask")
|
||||
: reviewResponse.json.optJSONObject("task")
|
||||
);
|
||||
});
|
||||
} catch (Exception error) {
|
||||
final JSONObject fallbackDraft = selectedDraft;
|
||||
runOnUiThread(() -> {
|
||||
if (fallbackDraft != null) {
|
||||
applyPayload(fallbackDraft, null);
|
||||
applyPayload(fallbackDraft, null, null);
|
||||
} else {
|
||||
setRefreshing(false);
|
||||
}
|
||||
@@ -337,7 +400,7 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
}
|
||||
runOnUiThread(() -> {
|
||||
showMessage("已清空当前勾选");
|
||||
applyPayload(response.json.optJSONObject("draft"), null);
|
||||
applyPayload(response.json.optJSONObject("draft"), null, null);
|
||||
});
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> {
|
||||
@@ -362,7 +425,7 @@ public class DeviceImportDraftActivity extends BossScreenActivity {
|
||||
}
|
||||
runOnUiThread(() -> {
|
||||
showMessage("已应用导入");
|
||||
applyPayload(response.json.optJSONObject("draft"), response.json.optJSONObject("resolution"));
|
||||
applyPayload(response.json.optJSONObject("draft"), response.json.optJSONObject("resolution"), null);
|
||||
});
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> {
|
||||
|
||||
Reference in New Issue
Block a user