diff --git a/apps/jingrow/frontend/src/core/pagetype/GenericListPage.vue b/apps/jingrow/frontend/src/core/pagetype/GenericListPage.vue index 1b5bdeb..96626e4 100644 --- a/apps/jingrow/frontend/src/core/pagetype/GenericListPage.vue +++ b/apps/jingrow/frontend/src/core/pagetype/GenericListPage.vue @@ -795,6 +795,10 @@ async function loadData() { // 添加过滤条件 const filterConditions: any[] = [] + + // 先处理非Link字段的过滤条件 + const linkFieldFilters: Array<{ fieldName: string; value: string; fieldMeta: any }> = [] + Object.entries(filters.value).forEach(([fieldName, value]) => { if (value !== null && value !== undefined && value !== '' && !(Array.isArray(value) && value.length === 0)) { @@ -806,12 +810,15 @@ async function loadData() { const fieldMeta = metaFields.value.find(f => f.fieldname === fieldName) const fieldType = fieldMeta?.fieldtype || '' - // 文本类型字段使用 like 操作符进行模糊搜索 - const isTextLikeField = ['Data', 'Text', 'Long Text', 'Comment', 'Link'].includes(fieldType) - - if (isTextLikeField && typeof value === 'string') { - // 使用 like 操作符,值前后添加 % 通配符 - filterConditions.push([fieldName, 'like', `%${value}%`]) + // Link字段类型:需要同时匹配字段值和title_field + if (fieldType === 'Link' && typeof value === 'string' && fieldMeta?.options) { + // 收集Link字段过滤条件,稍后处理 + linkFieldFilters.push({ fieldName, value: value as string, fieldMeta }) + } else if (['Data', 'Text', 'Long Text', 'Comment'].includes(fieldType)) { + // 文本类型字段使用 like 操作符进行模糊搜索 + if (typeof value === 'string') { + filterConditions.push([fieldName, 'like', `%${value}%`]) + } } else { // 其他类型字段使用精确匹配 filterConditions.push([fieldName, '=', value]) @@ -820,6 +827,91 @@ async function loadData() { } }) + // 处理Link字段的过滤:需要搜索关联记录的title_field + for (const linkFilter of linkFieldFilters) { + const { fieldName, value, fieldMeta } = linkFilter + const linkedPagetype = fieldMeta.options + + try { + // 获取关联pagetype的配置 + const config = await getPageTypeConfig(linkedPagetype) + const titleField = config.title_field || 'name' + + // 构建匹配的name值列表 + const matchedNames = new Set() + + // 1. 先匹配Link字段值(name字段)本身 + if (value) { + matchedNames.add(value) // 精确匹配 + // 也支持模糊匹配name字段 + } + + // 2. 如果title_field不是name且启用了show_title_field_in_link,搜索title_field + if (titleField !== 'name' && config.show_title_field_in_link) { + try { + // 搜索关联pagetype的title_field + const searchFilters = [[titleField, 'like', `%${value}%`]] + const searchResult = await axios.get(`/api/data/${encodeURIComponent(linkedPagetype)}`, { + params: { + fields: JSON.stringify(['name']), + filters: JSON.stringify(searchFilters), + limit_page_length: 100 // 限制最多100条,避免性能问题 + }, + headers: get_session_api_headers(), + withCredentials: true + }) + + const matchedRecords = searchResult.data?.data || [] + matchedRecords.forEach((record: any) => { + if (record.name) { + matchedNames.add(record.name) + } + }) + } catch (error) { + console.warn(`搜索${linkedPagetype}的title_field失败:`, error) + } + } else if (titleField === 'name') { + // 如果title_field就是name,直接使用like匹配 + // 使用OR条件:匹配name本身或name字段like + // 由于后端可能不支持OR,我们使用in操作符,包含value和可能的匹配值 + // 先搜索匹配的记录 + try { + const searchFilters = [['name', 'like', `%${value}%`]] + const searchResult = await axios.get(`/api/data/${encodeURIComponent(linkedPagetype)}`, { + params: { + fields: JSON.stringify(['name']), + filters: JSON.stringify(searchFilters), + limit_page_length: 100 + }, + headers: get_session_api_headers(), + withCredentials: true + }) + + const matchedRecords = searchResult.data?.data || [] + matchedRecords.forEach((record: any) => { + if (record.name) { + matchedNames.add(record.name) + } + }) + } catch (error) { + console.warn(`搜索${linkedPagetype}的name字段失败:`, error) + } + } + + // 如果有匹配的name值,使用in操作符 + if (matchedNames.size > 0) { + filterConditions.push([fieldName, 'in', Array.from(matchedNames)]) + } else { + // 如果没有匹配值,使用like匹配字段值本身 + filterConditions.push([fieldName, 'like', `%${value}%`]) + } + } catch (error) { + console.warn(`处理Link字段${fieldName}过滤失败,使用字段值匹配:`, error) + // 降级方案:直接使用like匹配字段值 + filterConditions.push([fieldName, 'like', `%${value}%`]) + } + } + if (filterConditions.length > 0) { params.filters = JSON.stringify(filterConditions) }