feat(aihr): add scoped case detail view
This commit is contained in:
@@ -77,25 +77,43 @@
|
||||
</button>
|
||||
</view>
|
||||
<view v-if="records.length" class="record-list">
|
||||
<view v-for="record in records" :key="`${record.title}-${record.time}`" class="record-row">
|
||||
<view v-for="record in records" :key="`${record.caseId}-${record.title}-${record.time}`" class="record-row">
|
||||
<view>
|
||||
<text class="record-title">{{ record.title }}</text>
|
||||
<text class="record-desc">{{ record.time }} · {{ record.owner }} · {{ record.type }}</text>
|
||||
<text class="record-summary">{{ record.summary }}</text>
|
||||
</view>
|
||||
<text class="record-status">{{ record.status }}</text>
|
||||
<view class="record-actions">
|
||||
<text class="record-status">{{ record.status }}</text>
|
||||
<button class="secondary-button detail-button" :disabled="caseDetailLoading" @click="openCaseDetail(record)">查看详情</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="empty">暂无入库案例</view>
|
||||
</view>
|
||||
|
||||
<view v-if="caseDetail" class="panel case-detail-panel">
|
||||
<view class="section-head">
|
||||
<view>
|
||||
<text class="panel-title">案例详情</text>
|
||||
<text class="record-desc">{{ caseDetail.time }} · {{ caseDetail.owner }} · {{ caseDetail.status }}</text>
|
||||
</view>
|
||||
<button class="ghost-button refresh-button" @click="caseDetail = null">关闭</button>
|
||||
</view>
|
||||
<text class="detail-label">原始转写</text>
|
||||
<text class="case-content">{{ caseDetail.transcript || '暂无转写内容' }}</text>
|
||||
<text class="detail-label">案例摘要</text>
|
||||
<text class="case-note">{{ caseDetail.summary || '暂无案例摘要' }}</text>
|
||||
<text class="case-note">当前版本提供转写、摘要和状态详情;视频样片、学习点与主管点评待正式媒体和业务字段接入。</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import { onShow } from '@dcloudio/uni-app';
|
||||
import type { CaseCurateResponse, CaseOrganizeResponse, CaseRecord, CaseSelectedFile, CaseUploadResponse } from '@/types/api';
|
||||
import { chooseCaseAudio, curateCase, getCaseRecords, organizeCase, uploadCaseAudio } from '@/services/case';
|
||||
import type { CaseCurateResponse, CaseDetailResponse, CaseOrganizeResponse, CaseRecord, CaseSelectedFile, CaseUploadResponse } from '@/types/api';
|
||||
import { chooseCaseAudio, curateCase, getCaseDetail, getCaseRecords, organizeCase, uploadCaseAudio } from '@/services/case';
|
||||
import { isLoggedIn, rememberLoginRedirect } from '@/services/auth';
|
||||
import { navigateBackToToday, resetPageScroll } from '@/services/navigation';
|
||||
import { ensureEmployeePosition } from '@/services/position';
|
||||
@@ -106,8 +124,10 @@ const uploadResult = ref<CaseUploadResponse | null>(null);
|
||||
const organizeResult = ref<CaseOrganizeResponse | null>(null);
|
||||
const curateResult = ref<CaseCurateResponse | null>(null);
|
||||
const records = ref<CaseRecord[]>([]);
|
||||
const caseDetail = ref<CaseDetailResponse | null>(null);
|
||||
const status = ref<'idle' | 'uploading' | 'organizing' | 'curating'>('idle');
|
||||
const recordsLoading = ref(false);
|
||||
const caseDetailLoading = ref(false);
|
||||
const message = ref('');
|
||||
const busy = computed(() => status.value !== 'idle');
|
||||
const statusText = computed(() => {
|
||||
@@ -126,6 +146,7 @@ const resetResult = () => {
|
||||
const clearCaseData = () => {
|
||||
selectedFile.value = null;
|
||||
records.value = [];
|
||||
caseDetail.value = null;
|
||||
resetResult();
|
||||
};
|
||||
|
||||
@@ -179,6 +200,19 @@ const refreshRecords = () => {
|
||||
void loadRecords();
|
||||
};
|
||||
|
||||
const openCaseDetail = async (record: CaseRecord) => {
|
||||
if (!record.caseId || caseDetailLoading.value) return;
|
||||
caseDetailLoading.value = true;
|
||||
message.value = '';
|
||||
try {
|
||||
caseDetail.value = await getCaseDetail(record.caseId);
|
||||
} catch (error) {
|
||||
handleRequestError(error, '案例详情加载失败');
|
||||
} finally {
|
||||
caseDetailLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const submitCase = async () => {
|
||||
if (!selectedFile.value || busy.value) return;
|
||||
message.value = '';
|
||||
@@ -310,6 +344,31 @@ onShow(() => {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.record-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.detail-button {
|
||||
min-width: 84px;
|
||||
padding: 6px 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.case-detail-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
color: #1a1a1a;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.tag-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
Reference in New Issue
Block a user