fix(personal): align assistant citations and UI state

This commit is contained in:
2026-07-12 12:07:28 +08:00
parent c8ef15ee9e
commit 36b7bf28bf
14 changed files with 181 additions and 61 deletions
@@ -25,6 +25,7 @@
<view v-else-if="message && !items.length" class="panel"><text class="status-message">{{ message }}</text><button class="secondary-button retry" @click="refresh">重试</button></view>
<view v-else-if="!items.length" class="panel empty">还没有个人资料,先收藏一条文字、文件或网页。</view>
<view v-else class="item-list">
<text v-if="message" class="status-message">{{ message }}</text>
<button v-for="item in items" :key="item.id" class="item-card employee-card" @click="openItem(item.id)">
<view class="item-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>
@@ -39,7 +40,7 @@
import { computed, ref } from 'vue';
import { onShow } from '@dcloudio/uni-app';
import type { PersonalItem, PersonalItemSourceType, PersonalItemStatus, PersonalSpace } from '@/types/api';
import { loadPersonalItems, loadPersonalSpace } from '@/services/personal-assistant';
import { loadPersonalItems, loadPersonalSpace, mergePersonalRows } from '@/services/personal-assistant';
const pageNum = ref(1);
const pageSize = 10;
@@ -51,14 +52,15 @@ const status = ref<PersonalItemStatus | ''>('');
const keyword = ref('');
const loading = ref(false);
const message = ref('');
let requestGeneration = 0;
const sourceOptions = [{ label: '全部来源', value: '' }, { label: '文字', value: 'TEXT' }, { label: '文件', value: 'FILE' }, { label: '网页', value: 'URL' }] as const;
const statusOptions = [{ label: '全部状态', value: '' }, { label: '等待处理', value: 'QUEUED' }, { label: '解析中', value: 'PARSING' }, { label: '可检索', value: 'READY' }, { label: '失败', value: 'FAILED' }] as const;
const sourceLabel = computed(() => sourceOptions.find((item) => item.value === sourceType.value)?.label || '全部来源');
const statusLabel = computed(() => statusOptions.find((item) => item.value === status.value)?.label || '全部状态');
const usagePercent = computed(() => Math.min(100, Math.round(((space.value?.usedBytes || 0) / Math.max(1, space.value?.quotaBytes || 1)) * 100)));
const load = async (append = false) => {
if (loading.value) return;
const load = async (append = false, pageSnapshot = pageNum.value) => {
const generation = ++requestGeneration;
loading.value = true;
message.value = '';
try {
@@ -66,15 +68,25 @@ const load = async (append = false) => {
loadPersonalItems({ pageNum: pageNum.value, pageSize, sourceType: sourceType.value, status: status.value, keyword: keyword.value.trim() }),
loadPersonalSpace()
]);
items.value = append ? [...items.value, ...page.rows] : page.rows;
if (generation !== requestGeneration || pageSnapshot !== pageNum.value) return;
items.value = append ? mergePersonalRows(items.value, page.rows) : page.rows;
total.value = page.total;
space.value = latestSpace;
} catch (error) {
if (generation !== requestGeneration) return;
if (append) pageNum.value = Math.max(1, pageSnapshot - 1);
message.value = error instanceof Error ? error.message : '资料加载失败';
} finally { loading.value = false; }
} finally {
if (generation === requestGeneration) loading.value = false;
}
};
const refresh = () => { pageNum.value = 1; void load(); };
const loadMore = () => { pageNum.value += 1; void load(true); };
const loadMore = () => {
if (loading.value) return;
const nextPage = pageNum.value + 1;
pageNum.value = nextPage;
void load(true, nextPage);
};
const changeSource = (event: { detail: { value: string | number } }) => { sourceType.value = sourceOptions[Number(event.detail.value)]?.value || ''; refresh(); };
const changeStatus = (event: { detail: { value: string | number } }) => { status.value = statusOptions[Number(event.detail.value)]?.value || ''; refresh(); };
const sourceText = (value: PersonalItemSourceType) => ({ TEXT: '文字', FILE: '文件', URL: '外部网页' })[value];