diff --git a/docs/BRD_IMPLEMENTATION_AUDIT.md b/docs/BRD_IMPLEMENTATION_AUDIT.md
index 9045104e..7c8c087f 100644
--- a/docs/BRD_IMPLEMENTATION_AUDIT.md
+++ b/docs/BRD_IMPLEMENTATION_AUDIT.md
@@ -243,3 +243,4 @@
- 2026-07-14 BRD 6.3 AI 面试记录回退语义复核:面试记录接口成功返回空列表时原先会错误替换为内置历史记录,接口失败时也只静默回退;现保留真实空列表,仅失败时展示演示记录并增加持久提示“当前显示演示记录,不代表真实面试数据”。该修复不改变面试题生成、评分或复核流程。
- 2026-07-14 BRD 6.3 复盘与 SOP 数据来源复核:复盘页在试点指标接口失败时原先用待复盘记录数代替校准样本数,现改为显示未知并持久提示接口不可用;SOP 文档表继续保留断网演示样例,但为内置演示/已上传记录增加来源标识和提示,避免把演示文档或列表数量误当真实库覆盖与 M5 指标。
- 2026-07-14 BRD 6.3 对练记录回退语义复核:管理端三角色对练页原先始终显示三条静态最近记录,未请求真实复盘记录;现改为 API 优先,真实空列表保持为空,只有接口失败才显示演示记录并持续提示。当前会话完成后追加到现有列表,不再重置时覆盖历史记录。
+- 2026-07-14 BRD 6.3 管理端记录首屏回退复核:面试、案例和三角色对练页此前在接口结果返回前就初始化内置 `baseRecords`,慢请求期间可能把演示记录误看成真实业务记录;现统一改为加载期间空表加 loading,只有接口明确失败后才展示演示记录并保留持久提示,真实空列表继续保持为空。补充 `demo-check` 静态标记,管理端 ESLint 与构建通过;本轮未发布生产。
diff --git a/frontend/src/views/knowledge/cases.vue b/frontend/src/views/knowledge/cases.vue
index 34f44488..cc16978f 100644
--- a/frontend/src/views/knowledge/cases.vue
+++ b/frontend/src/views/knowledge/cases.vue
@@ -118,7 +118,7 @@
最近案例
-
+
@@ -188,7 +188,7 @@ const apiSummary = ref([]);
const apiTags = ref([]);
const apiRecord = ref(null);
const apiSampleHint = ref('');
-const recordsLoading = ref(false);
+const recordsLoading = ref(true);
const recordsFallback = ref(false);
const detailVisible = ref(false);
const caseDetail = ref(null);
@@ -279,7 +279,7 @@ const baseRecords = [
}
];
-const records = ref([...baseRecords]);
+const records = ref([]);
async function loadCaseRecords() {
recordsLoading.value = true;
diff --git a/frontend/src/views/recruit/interview.vue b/frontend/src/views/recruit/interview.vue
index d30d4da6..2c8e5197 100644
--- a/frontend/src/views/recruit/interview.vue
+++ b/frontend/src/views/recruit/interview.vue
@@ -179,7 +179,7 @@
面试记录
-
+
@@ -481,7 +481,8 @@ const apiMode = ref<'idle' | 'api' | 'fallback'>('idle');
const apiQuestions = ref([]);
const apiScoreResult = ref(null);
const answers = reactive>({});
-const records = ref([...baseRecords]);
+const records = ref([]);
+const recordsLoading = ref(true);
const recordsFallback = ref(false);
const interviewReviewVisible = ref(false);
const interviewReviewSaving = ref(false);
@@ -680,6 +681,7 @@ const questionPillClass = (question: InterviewQuestion) => {
};
const loadInterviewRecords = async () => {
+ recordsLoading.value = true;
try {
const { data } = await listInterviewRecords(20);
records.value = data ?? [];
@@ -687,6 +689,8 @@ const loadInterviewRecords = async () => {
} catch {
records.value = [...baseRecords];
recordsFallback.value = true;
+ } finally {
+ recordsLoading.value = false;
}
};
diff --git a/frontend/src/views/train/practice.vue b/frontend/src/views/train/practice.vue
index a8c6f88d..1a2567b6 100644
--- a/frontend/src/views/train/practice.vue
+++ b/frontend/src/views/train/practice.vue
@@ -199,7 +199,7 @@
最近对练记录
-
+
@@ -485,8 +485,9 @@ const sopHelp = ref(null);
const sopHelpLoading = ref(false);
const sopHelpMessage = ref('');
const conversation = ref([]);
-const records = ref([...baseRecords]);
-const recordsFallback = ref(true);
+const records = ref>([]);
+const recordsLoading = ref(true);
+const recordsFallback = ref(false);
const promptTemplates = ref([]);
const promptLoading = ref(false);
const promptSaving = ref(false);
@@ -655,6 +656,7 @@ const loadScenarioOptions = async () => {
};
const loadRecentRecords = async () => {
+ recordsLoading.value = true;
try {
const { data } = await listPracticeReviews({ limit: 10 });
records.value = (data || []).map((item) => ({
@@ -669,6 +671,8 @@ const loadRecentRecords = async () => {
} catch {
records.value = [...baseRecords];
recordsFallback.value = true;
+ } finally {
+ recordsLoading.value = false;
}
};
diff --git a/scripts/demo-check.sh b/scripts/demo-check.sh
index 2a324a66..7e016824 100755
--- a/scripts/demo-check.sh
+++ b/scripts/demo-check.sh
@@ -383,8 +383,14 @@ contains mobile-uni/src/pages/user/learning/index.vue "getPracticeAssignments"
contains mobile-uni/src/pages/user/learning/index.vue "searchKnowledge"
contains mobile-uni/src/pages/user/learning/index.vue "getPracticePrepCard"
contains frontend/src/views/recruit/interview.vue "建议复试"
+contains frontend/src/views/recruit/interview.vue 'v-loading="recordsLoading"'
+contains frontend/src/views/recruit/interview.vue "const recordsLoading = ref(true)"
contains frontend/src/views/train/practice.vue "导师改写"
+contains frontend/src/views/train/practice.vue 'v-loading="recordsLoading"'
+contains frontend/src/views/train/practice.vue "const records = ref>([])"
contains frontend/src/views/knowledge/cases.vue "真实语音"
+contains frontend/src/views/knowledge/cases.vue 'v-loading="recordsLoading"'
+contains frontend/src/views/knowledge/cases.vue "const records = ref([])"
contains frontend/src/views/knowledge/cases.vue "案例所属项目"
contains frontend/src/views/knowledge/cases.vue "请先选择案例所属项目"
contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrCaseService.java "系统用户上传案例必须明确所属项目"