From c9c2d6ec6274d0687b6ad56ad4a7d253092c32bf Mon Sep 17 00:00:00 2001 From: jingrow Date: Sat, 1 Nov 2025 14:54:23 +0800 Subject: [PATCH] =?UTF-8?q?pagetype=E5=88=97=E8=A1=A8=E9=A1=B5Link?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E7=9A=84=E5=AD=97=E6=AE=B5=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E4=B8=BA=E6=98=BE=E7=A4=BAtitle=5Ffield=E7=9A=84=E5=80=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/core/components/FilterBar.vue | 3 + .../src/core/pagetype/GenericListPage.vue | 126 +++++++++++++++++- 2 files changed, 127 insertions(+), 2 deletions(-) diff --git a/apps/jingrow/frontend/src/core/components/FilterBar.vue b/apps/jingrow/frontend/src/core/components/FilterBar.vue index 0f1b9a0..029fc55 100644 --- a/apps/jingrow/frontend/src/core/components/FilterBar.vue +++ b/apps/jingrow/frontend/src/core/components/FilterBar.vue @@ -23,6 +23,7 @@ size="small" @blur="onFilterChange" @update:value="onInputChange" + @keyup.enter="onFilterChange" /> @@ -78,6 +79,7 @@ size="small" @blur="onFilterChange" @update:value="onInputChange" + @keyup.enter="onFilterChange" /> @@ -102,6 +104,7 @@ size="small" @blur="onFilterChange" @update:value="onInputChange" + @keyup.enter="onFilterChange" /> diff --git a/apps/jingrow/frontend/src/core/pagetype/GenericListPage.vue b/apps/jingrow/frontend/src/core/pagetype/GenericListPage.vue index 6806310..d068145 100644 --- a/apps/jingrow/frontend/src/core/pagetype/GenericListPage.vue +++ b/apps/jingrow/frontend/src/core/pagetype/GenericListPage.vue @@ -289,6 +289,8 @@ const cardBadges = computed(() => { }) const metaFields = ref([]) +const linkTitleCache = ref>({}) +const pageTypeConfigCache = ref>({}) async function loadMeta() { loading.value = true @@ -304,6 +306,110 @@ async function loadMeta() { } } +// 获取页面类型配置 +async function getPageTypeConfig(pagetype: string) { + if (!pagetype) return {} + + // 检查缓存 + if (pageTypeConfigCache.value[pagetype]) { + return pageTypeConfigCache.value[pagetype] + } + + try { + const response = await axios.get(`/api/data/PageType/${encodeURIComponent(pagetype)}`, { + headers: get_session_api_headers(), + withCredentials: true + }) + + const config = response.data?.data || {} + pageTypeConfigCache.value[pagetype] = config + return config + } catch (error) { + console.error('获取页面类型配置失败:', error) + return {} + } +} + +// 获取记录的标题字段值 +async function getRecordTitle(pagetype: string, recordName: string): Promise { + if (!pagetype || !recordName) return recordName || '' + + // 检查缓存 + const cacheKey = `${pagetype}_${recordName}` + if (linkTitleCache.value[cacheKey]) { + return linkTitleCache.value[cacheKey] + } + + try { + // 获取页面类型配置 + const config = await getPageTypeConfig(pagetype) + const titleField = config.title_field || 'name' + const showTitleFieldInLink = config.show_title_field_in_link || false + + // 如果标题字段就是name,直接返回 + if (titleField === 'name') { + linkTitleCache.value[cacheKey] = recordName + return recordName + } + + // 如果未启用show_title_field_in_link,直接返回原值 + if (!showTitleFieldInLink) { + linkTitleCache.value[cacheKey] = recordName + return recordName + } + + // 获取记录数据 + const response = await axios.get(`/api/data/${encodeURIComponent(pagetype)}/${encodeURIComponent(recordName)}`, { + headers: get_session_api_headers(), + withCredentials: true + }) + + const recordData = response.data?.data || {} + const titleValue = recordData[titleField] || recordName + + // 缓存结果 + linkTitleCache.value[cacheKey] = titleValue + return titleValue + + } catch (error) { + console.error('获取记录标题失败:', error) + return recordName + } +} + +// 预加载Link字段的title_field值 +async function preloadLinkTitles() { + // 找到所有Link类型的字段 + const linkFields = metaFields.value.filter(f => f.fieldtype === 'Link' && f.options) + + if (linkFields.length === 0) return + + // 收集所有需要加载的Link字段值,使用Map去重 + const linkMap = new Map() + + rows.value.forEach(row => { + linkFields.forEach(field => { + const value = row[field.fieldname] + if (value) { + const key = `${field.options}::${value}` + if (!linkMap.has(key)) { + linkMap.set(key, { + pagetype: field.options, + recordName: value + }) + } + } + }) + }) + + // 批量加载title_field值 + await Promise.all( + Array.from(linkMap.values()).map(({ pagetype, recordName }) => + getRecordTitle(pagetype, recordName).catch(() => recordName) + ) + ) +} + async function loadData() { loading.value = true try { @@ -356,6 +462,11 @@ async function loadData() { } else { total.value = res.data.total } + + // 预加载Link字段的title_field值(后台执行,不阻塞UI) + preloadLinkTitles().catch(err => { + console.error('预加载Link标题失败:', err) + }) } catch (error) { console.error('Load data error:', error) message.error(t('Load failed')) @@ -479,9 +590,20 @@ function isBooleanField(fieldName: string) { function formatDisplayValue(value: any, fieldName: string) { let result: any = value - // 尝试从字段元数据获取翻译选项 + // 获取字段元数据 const fieldMeta = metaFields.value.find(f => f.fieldname === fieldName) - if (fieldMeta && fieldMeta.options) { + + // 如果是Link类型字段,使用缓存的title_field值 + if (fieldMeta && fieldMeta.fieldtype === 'Link' && fieldMeta.options && value) { + const cacheKey = `${fieldMeta.options}_${value}` + if (linkTitleCache.value[cacheKey]) { + result = linkTitleCache.value[cacheKey] + } else { + // 如果缓存中没有,返回原值(可能正在加载中) + result = value + } + } else if (fieldMeta && fieldMeta.options) { + // 尝试从字段元数据获取翻译选项(非Link字段) const options = fieldMeta.options.split('\n').filter((s: string) => s.trim() !== '') if (options.includes(value)) { result = t(value)