feat(mobile): add personal assistant knowledge flow
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<view class="page employee-page-shell item-page">
|
||||
<view class="subpage-header"><button class="subpage-back-button" @click="goBack">‹</button><view class="subpage-heading"><text class="page-title">资料详情</text><text class="page-subtitle">解析正文只读,状态来自服务端</text></view></view>
|
||||
<view v-if="loading" class="panel empty">加载中…</view>
|
||||
<view v-else-if="message && !item" class="panel"><text class="status-message">{{ message }}</text><button class="secondary-button full-button" @click="load">重试</button></view>
|
||||
<template v-else-if="item">
|
||||
<view class="panel employee-card detail-card">
|
||||
<view class="detail-head"><text class="source-badge">{{ sourceText(item.sourceType) }}</text><text class="status-badge" :class="item.status.toLowerCase()">{{ statusText(item.status) }}</text></view>
|
||||
<text class="item-title">{{ item.title || '未命名资料' }}</text>
|
||||
<text class="meta">收藏时间:{{ item.capturedAt || '未记录' }}</text>
|
||||
<text v-if="item.originalUrl" class="meta">网页来源:{{ item.originalUrl }}</text>
|
||||
<text v-if="item.tags?.length" class="meta">标签:{{ item.tags.join('、') }}</text>
|
||||
</view>
|
||||
<view class="panel employee-card status-card">
|
||||
<text class="panel-title">处理状态</text>
|
||||
<text class="status-copy">{{ statusDescription(item.status) }}</text>
|
||||
<text v-if="item.errorMessage" class="status-message">{{ item.errorMessage }}</text>
|
||||
<button v-if="item.status === 'FAILED'" class="primary-button full-button" :disabled="busy" @click="retry">{{ busy ? '重试中' : '重新解析' }}</button>
|
||||
<button v-if="item.sourceType === 'FILE' && item.status === 'READY'" class="secondary-button full-button" :disabled="busy" @click="download">下载原附件</button>
|
||||
</view>
|
||||
<view v-if="item.summary" class="panel employee-card"><text class="panel-title">内容摘要</text><text class="summary">{{ item.summary }}</text></view>
|
||||
<view class="panel danger-panel">
|
||||
<text class="panel-title danger-title">删除资料</text>
|
||||
<text class="danger-copy">删除后,附件、解析正文和搜索索引会清除,且无法恢复。</text>
|
||||
<button class="secondary-button danger-button" :disabled="busy || item.status === 'DELETING'" @click="confirmDelete">{{ item.status === 'DELETING' ? '删除中' : '删除资料' }}</button>
|
||||
</view>
|
||||
<text v-if="message" class="status-message">{{ message }}</text>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { onLoad } from '@dcloudio/uni-app';
|
||||
import type { PersonalItem, PersonalItemSourceType, PersonalItemStatus } from '@/types/api';
|
||||
import { deletePersonalItem, downloadPersonalItem, loadPersonalItem, retryPersonalItem } from '@/services/personal-assistant';
|
||||
|
||||
const itemId = ref(0); const item = ref<PersonalItem>(); const loading = ref(false); const busy = ref(false); const message = ref('');
|
||||
const statusText = (status: PersonalItemStatus) => ({ QUEUED: '等待处理', PARSING: '解析中', READY: '可检索', FAILED: '解析失败', DELETING: '删除中', DELETED: '已删除' })[status];
|
||||
const statusDescription = (status: PersonalItemStatus) => ({ QUEUED: '已进入解析队列。', PARSING: '正在提取正文和建立搜索索引。', READY: '已完成解析,可用于个人助理问答。', FAILED: '本次解析失败,可查看公开原因后重试。', DELETING: '正在清理附件、正文和索引。', DELETED: '资料已删除。' })[status];
|
||||
const sourceText = (source: PersonalItemSourceType) => ({ TEXT: '文字', FILE: '文件', URL: '外部网页' })[source];
|
||||
const load = async () => { if (!itemId.value) return; loading.value = true; message.value = ''; try { item.value = await loadPersonalItem(itemId.value); } catch (error) { message.value = error instanceof Error ? error.message : '资料不存在或无权访问'; } finally { loading.value = false; } };
|
||||
const retry = async () => { busy.value = true; message.value = ''; try { item.value = await retryPersonalItem(itemId.value); } catch (error) { message.value = error instanceof Error ? error.message : '重试失败'; } finally { busy.value = false; } };
|
||||
const download = async () => { busy.value = true; try { const result = await downloadPersonalItem(itemId.value); if (!result.url) throw new Error('附件下载地址不可用'); if (typeof window !== 'undefined') window.open(result.url, '_blank', 'noopener,noreferrer'); else uni.downloadFile({ url: result.url }); } catch (error) { message.value = error instanceof Error ? error.message : '下载失败'; } finally { busy.value = false; } };
|
||||
const confirmDelete = () => uni.showModal({ title: '确认删除资料', content: '附件、解析正文和搜索索引会清除,删除后无法恢复。', confirmText: '确认删除', confirmColor: '#e70014', success: (result) => { if (result.confirm) void remove(); } });
|
||||
const remove = async () => { busy.value = true; message.value = ''; try { await deletePersonalItem(itemId.value); uni.redirectTo({ url: '/pages/user/assistant/library' }); } catch (error) { message.value = error instanceof Error ? error.message : '删除失败,请重试'; } finally { busy.value = false; } };
|
||||
const goBack = () => uni.navigateBack();
|
||||
onLoad((options) => { itemId.value = Number(options?.id || 0); if (!Number.isSafeInteger(itemId.value) || itemId.value <= 0) message.value = '资料不存在或无权访问'; else void load(); });
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.item-page { overflow-x: hidden; }.detail-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }.source-badge, .status-badge { padding: 4px 8px; border-radius: var(--radius); background: #eef3f9; color: var(--knowledge); font-size: 12px; }.status-badge.ready { color: var(--success); }.status-badge.failed, .danger-title { color: #b42318; }.item-title, .meta, .summary, .status-copy, .danger-copy { display: block; }.item-title { margin-top: 14px; font-size: 20px; font-weight: 900; }.meta { margin-top: 8px; color: var(--muted); font-size: 13px; overflow-wrap: anywhere; }.status-copy, .summary, .danger-copy { margin-top: 10px; line-height: 1.65; }.summary { white-space: pre-wrap; }.full-button { width: 100%; margin-top: 12px; }.danger-panel { border-color: #f5c2c7; }.danger-button { color: #b42318; }
|
||||
</style>
|
||||
Reference in New Issue
Block a user