xwiki livedata筛选和分页

xwiki livedata

前文中我们自定义页面,让livedata去加载自动定义页面,实现实时数据展示。发现有一个问题 ,筛选的时候没有正确显示数据

1、f12 查看接口请求

http://localhost:8080/xwiki/rest/liveData/sources/liveTable/entries?timestamp=1756188130870\&namespace=wiki%3Axwiki\&sourceParams.resultPage=xwiki%3Af.WebHome\&sourceParams.translationPrefix=admin.livetable.\&sourceParams.queryFilters=currentlanguage%2Chidden\&properties=id\&properties=name\&properties=level\&properties=parentId\&offset=0\&limit=15\&filters.name=contains%3Af\&sort=id\&descending=

使用url解码

http://localhost:8080/xwiki/rest/liveData/sources/liveTable/entries?timestamp=1756188130870\&namespace=wiki:xwiki\&sourceParams.resultPage=xwiki:f.WebHome\&sourceParams.translationPrefix=admin.livetable.\&sourceParams.queryFilters=currentlanguage,hidden\&properties=id\&properties=name\&properties=level\&properties=parentId\&offset=0\&limit=15\&filters.name=contains:f\&sort=id\&descending=

2.修改之前的自定义页面

复制代码
{{groovy}}
import groovy.json.JsonOutput
import org.slf4j.Logger
import java.net.URLDecoder

// 获取 SLF4J 日志器
def logger = services.logging.getLogger("LiveTableScript")

// 设置 JSON 内容类型
if (request?.getParameter("xpage") == "plain") {
    response.setContentType("application/json")
}

// 模拟数据库数据(根据之前的输出包含 8 条记录)
def all = [
    [id: "620000000000000", name: "甘肃省", level: 1, parentId: "0"],
    [id: "621000000000000", name: "甘肃省1", level: 1, parentId: "0"],
    [id: "630000000000000", name: "青海省", level: 1, parentId: "0"],
    [id: "631000000000000", name: "青海省2", level: 1, parentId: "0"],
    [id: "640000000000000", name: "宁夏回族自治区", level: 1, parentId: "0"],
    [id: "641000000000000", name: "宁夏回族自治区3", level: 1, parentId: "0"],
    [id: "650000000000000", name: "新疆维吾尔自治区", level: 1, parentId: "0"],
    [id: "651000000000000", name: "新疆维吾尔自治区4", level: 1, parentId: "0"]
]

// 处理参数
def offset = (request?.getParameter("offset") ?: "0") as int
def limit = (request?.getParameter("limit") ?: "15") as int
// 尝试多种可能的参数名并解码中文字符
def searchName = null
def rawSearch = request?.getParameter("filters.name") ?:
                request?.getParameter("filter.name") ?:
                request?.getParameter("name")
if (rawSearch) {
    searchName = URLDecoder.decode(rawSearch.replaceFirst(/^contains:/, '').trim(), "UTF-8")
}
def sort = request?.getParameter("sort") ?: "id"
def dir = request?.getParameter("dir")?.toLowerCase() ?: "asc"

// 记录调试日志到 XWiki 日志
logger.debug("Request parameters: {}", request?.parameterMap)
logger.debug("Search value: {}", searchName)

// 过滤逻辑
def filtered = all
if (searchName) {
    filtered = all.findAll { it.name.contains(searchName) }
    logger.debug("Filtered results: {}", filtered)
}

// 排序逻辑
if (dir == "desc") {
    filtered = filtered.sort { a, b -> -(a[sort] ?: 0) <=> (b[sort] ?: 0) }
} else {
    filtered = filtered.sort { a, b -> (a[sort] ?: 0) <=> (b[sort] ?: 0) }
}

// 计算总数
def totalCount = filtered.size() ?: 0
def entries = filtered.drop(offset).take(limit)

// 构造 Live Table JSON
def result = [
    totalrows: totalCount,
    returnedrows: entries.size(),
    offset: offset + 1,
    reqNo: (request?.getParameter("reqNo") ?: "1") as int,
    rows: entries.collect { entry ->
        def row = [
            id: entry.id,
            name: entry.name,
            level: entry.level,
            parentId: entry.parentId,
            doc_viewable: true
        ]
        return row
    }
]

// 输出 JSON
print JsonOutput.toJson(result)
{{/groovy}}

3.分页问题

这里反生了有意思问题,输入甘肃只显示其中一个。

通过打印日志发现,请求的时候offset被设置为1,导致数据从1开始查询, XWiki LiveData offset 从 1 开始,这里要减 1 转换成 list 的 0 基准,修复语法

复制代码
{{groovy}}
import groovy.json.JsonOutput
import org.slf4j.Logger
import java.net.URLDecoder

def logger = services.logging.getLogger("LiveTableScript")

if (request?.getParameter("xpage") == "plain") {
    response.setContentType("application/json; charset=UTF-8")
}

def all = [
    [id: "620000000000000", name: "甘肃省", level: 1, parentId: "0"],
    [id: "621000000000000", name: "甘肃省1", level: 1, parentId: "0"],
    [id: "630000000000000", name: "青海省", level: 1, parentId: "0"],
    [id: "631000000000000", name: "青海省2", level: 1, parentId: "0"],
    [id: "640000000000000", name: "宁夏回族自治区", level: 1, parentId: "0"],
    [id: "641000000000000", name: "宁夏回族自治区3", level: 1, parentId: "0"],
    [id: "650000000000000", name: "新疆维吾尔自治区", level: 1, parentId: "0"],
    [id: "651000000000000", name: "新疆维吾尔自治区4", level: 1, parentId: "0"]
]

// ==== 参数处理 ====
// XWiki LiveData offset 从 1 开始,这里要减 1 转换成 list 的 0 基准
def rawOffset = (request?.getParameter("offset") ?: "1") as int
def offset = rawOffset > 0 ? rawOffset - 1 : 0
def limit = (request?.getParameter("limit") ?: "15") as int
def sortField = request?.getParameter("sort") ?: "id"
def dir = request?.getParameter("descending") == "true" ? "desc" : "asc"
def rawSearch = request?.getParameter("filters.name") ?:
                request?.getParameter("filter.name") ?:
                request?.getParameter("name")
def searchName = rawSearch ? URLDecoder.decode(rawSearch.replaceFirst(/^contains:/, '').trim(), "UTF-8") : null

logger.debug("Request URL: {}", request?.requestURL)
logger.debug("Request parameters: {}", request?.parameterMap)
logger.debug("Raw offset parameter: {}", rawOffset)
logger.debug("Converted offset (0-based): {}", offset)
logger.debug("Limit: {}", limit)
logger.debug("Raw search parameter: {}", rawSearch)
logger.debug("Decoded search value: {}", searchName)
logger.debug("Sort field: {}", sortField)
logger.debug("Sort direction: {}", dir)

// ==== 过滤 ====
def filtered = all
if (searchName) {
    filtered = all.findAll { record ->
        def normalizedName = record.name.trim()
        normalizedName.contains(searchName)
    }
    logger.debug("Filtered results: {}", filtered)
}

// ==== 排序 ====
if (filtered) {
    filtered = filtered.sort { a, b ->
        def valA = a[sortField] ?: (sortField == "name" ? "" : 0)
        def valB = b[sortField] ?: (sortField == "name" ? "" : 0)
        dir == "desc" ? -(valA <=> valB) : (valA <=> valB)
    }
}

// ==== 分页 ====
def totalCount = filtered.size() ?: 0
def entries = filtered.drop(offset).take(limit)

logger.debug("Paginated entries: {}", entries)

// ==== 输出 ====
def result = [
    totalrows   : totalCount,
    returnedrows: entries.size(),
    offset      : rawOffset,  
    reqNo       : (request?.getParameter("reqNo") ?: "1") as int,
    rows        : entries.collect { entry ->
        [
            id         : entry.id,
            name       : entry.name,
            level      : entry.level,
            parentId   : entry.parentId,
            doc_viewable: true
        ]
    }
]

print JsonOutput.toJson(result)
{{/groovy}}

已经可以筛选和分页了,后边会接入实时数据。

相关推荐
碳基硅坊4 天前
使用RAGFlow搭建本地知识库
人工智能·知识库·rag·ragflow
AI玫瑰助手4 天前
PDF 转 Markdown 主力方案怎么选:PaddleOCR-VL-1.5、MinerU、HunyuanOCR 与 MonkeyOCR 实测对比
pdf·大模型·知识库·表格·md·文字识别·paddleocr
养肥胖虎7 天前
RAG学习笔记:让大模型先查资料再回答问题
ai·知识库·rag
梦想不只是梦与想8 天前
rag和agent的区别
人工智能·python·知识库·rag·智能体·agent‌
53AI9 天前
制造业智能安全生产监控:从“被动应对“到“主动预防“的转型之路
安全·知识库·制造业·预警
老码观察10 天前
数环通iPaaS知识库选型实践:从技术评估到RAGFlow深度调优
人工智能·agent·知识库
IPHWT 零软网络13 天前
AI Agent知识库功能解析:多源接入、动态更新与智能检索的技术价值
人工智能·科技·知识库
快跑bug来啦13 天前
RAGFlow部署教程:Ubuntu24.04
ai·大模型·知识图谱·知识库·rag
容智信息14 天前
不写SQL,不拉Excel:数据分析用“问”的
数据库·人工智能·笔记·数据分析·excel·知识图谱·知识库
安逸sgr18 天前
Hermes Agent + Obsidian 打造第二大脑(六):分层记忆系统的设计逻辑——L0/L1/L2/L3 四层记忆详解
数据库·agent·知识库·hermes·hermesagent