构建与修改动态列表配置

SKILL运维和基础设施

原名 pacp-build-list(动态列表构建器) · 标识 pacp-build-list

运维和基础设施 未标注权限 许可证不明确
安装这个技能

按规格文档或列表编号,构建列定义、查询条件、按钮与脚本绑定的列表配置,并通过接口提交到远程 PowerData 平台,属于远程配置数据操作。

一句话选型结论

按资料字段整理

构建与修改动态列表配置是运维和基础设施类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类运维和基础设施 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_ee9b2ae1/pacp-build-list
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

运维和基础设施
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_ee9b2ae1仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验2026-11-06上游最后核验时间 · 数据更新 2026-11-06
正文体量54.8 KBSKILL.md 原文大小,越大说明说明书写得越细

能做什么

0 项能力
上游给出的能力概览与适用场景
新建动态列表配置修改现有列表设置配置查询与按钮

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
查服务与日志

按现象定位服务状态与日志线索。

写部署与巡检脚本

把重复的部署、巡检写成脚本。

故障排查

按步骤排查网络、依赖与配置。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在运维和基础设施场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
构建与修改动态列表配置当前 未标注权限 未标注 未标注 未标注 有
Azure 部署 调用外部服务 GitHub 仓库 664.2 万 Codex、Claude、Cursor 有
Azure diagnostics 问题管理 调用外部服务 GitHub 仓库 657.6 万 Codex、Claude、Cursor 有
Azure aigateway 部署 调用外部服务 GitHub 仓库 655.3 万 Codex、Claude、Cursor 有
Azure AI 搜索 调用外部服务 GitHub 仓库 651.4 万 Codex、Claude、Cursor 有
Azure Cloud migrate 部署 调用外部服务 GitHub 仓库 650.7 万 Codex、Claude、Cursor 有

SKILL.md 全文

54.8 KB
模型实际读到的说明书原文,来自技能仓库

Build List(动态列表构建器)

读取 list-spec.md(新增)或 列表 XH(修改),构建列表配置并提交平台。

> ⚠️ 本技能是远程配置操作,不是代码开发任务。 通过 HTTP API 在远程 PowerData 平台上创建/修改列表配置数据,与当前项目源码完全无关。
> - 禁止:因为 cwd 在项目目录就去 ls / rg --files / 读业务代码,或用 read_file / module_report / read_symbol / ast_grep / lsp_* 探查项目结构与代码。
> - 数据来源只有三个:① 远程 API(表结构、字段元数据、代码集)② 本 SKILL.md ③ 用户提供(spec 或列表 XH)。本地代码库里没有任何你需要的东西。

🔴 HARD-GATE:新增必须 spec,修改按有无 spec 分流

> [!important] 硬约束,不可协商
> 【新增入口】唯一输入是 list-spec.md。禁止从用户口语/图片直接推断并构建列表。
> 用户没给 spec/业务名 → 停止,引导去 pacp-design-list。
> 【修改入口】输入是列表 XH + 修改意图,按是否有 spec 分流:
> - 有 spec(构建记录段匹配到该 XH)→ 改 spec → 重新构建覆盖线上,保持 spec 与线上一致
> - 无 spec(无任何 list-spec 构建记录匹配该 XH)→ 直接拉线上配置修改,不回写 spec;可提示用户用 design-list 补 spec 以便后续复用
> 反查机制:用列表 XH 扫描 .pacp/specs/动态渲染/*__列表.md 的「## 构建记录」段匹配。
> 两条入口都不接受"凭口语直接构建"。

> [!warning] 一致性提醒(有 spec 重建场景)
> 若列表曾被绕过 spec 直接在线上改过,"走 spec 重建"会用 spec 覆盖线上手工改动——重建前需提示用户确认。

反合理化表(AI 跳过 spec 的借口及反驳):

AI 内心独白(Red Flag) 反驳
"这列表就几列,直接生成了吧" 几列也要 spec——列类型/宽度/查询条件/系统列没确认,生成必跑偏
"用户描述很清楚了,我直接构建" 口语清晰 ≠ spec 完整。代码集编号?主键?多表关联关系?没确认就是赌
"我先建个草稿再让用户改" 草稿赌错方向,用户改的成本 > 先出 spec 对齐的成本
"spec 阶段太慢,用户等不及" spec 是一次性对齐,构建是落子无悔。慢在前面省在后面

统一工作根目录:.pacp/

> [!important] 所有 pacp-* skill 共用 .pacp/ 作为工作根目录

定位方式:AI 运行时的 cwd(当前工作目录)下的 .pacp/。

> [!warning] cwd 边界
> "别探查项目结构"约束依然成立——AI 只往 .pacp/ 读写工作文件,不触碰项目内其他任何文件。

{cwd}/.pacp/
  specs/                    ← list-spec.md(pacp-design-list 产出,本 skill 读取)
    动态渲染/                 ← design 产出的隔离子文件夹(优先查找)
      {业务名}__列表.md         ← 列表 spec(新命名,design 产出,最优先)
      {业务名}__表单.md         ← 表单 spec(关联表单字段引用其文件名 + 构建记录段取 templateId)
      {业务名}.md              ← 旧命名兜底(兼容迁移前的 spec)
  session.json              ← 共享会话凭证(本 skill 启动时读取复用)
  active/                   ← 工作区(trace、构建脚本、payload、列对照表)
    {业务名}_{时间戳}/
      field-mapping.md        ← spec→config 列对照表(构建前置产物)
      list-config.json        ← 从 spec 映射出的构建配置(喂给 list_creator.js)

> [!important] session 跨 skill 共享
> 启动时先读 .pacp/session.json,有效则直接复用;过期(401)则重新调 pacp-system-login 并更新。session.json 是可选缓存优化。

入口分流 + 文件存在性闸门

启动第一件事——按入口类型分流:

启动分流:
1. 修改入口(用户给了列表 XH + 修改意图)
   → 反查 spec:扫描 .pacp/specs/动态渲染/*__列表.md 的「## 构建记录」段,匹配列表 XH
     ├─ 命中 spec(某 spec 构建记录的「列表 XH」= 用户给的 XH)→ 走 spec 重建:改 spec → 重新构建覆盖线上
     └─ 未命中任何 spec → 走直改线上:getQueryConfig(XH) → 推断改动并生成 diff → 用户确认 → 提交(不回写 spec)

2. 新增入口(默认)
   → 文件存在性闸门:
   a. 用户给了业务名 → 按优先级查 spec 文件是否存在(命中即停,后者仅兜底):
      ① .pacp/specs/动态渲染/{业务名}__列表.md(新命名,design 产出,最优先)
      ② .pacp/specs/动态渲染/{业务名}.md(旧命名兜底,兼容迁移前的 spec)
      ├─ 存在 → 轻量校验(元信息段 + 列定义段存在且非空)→ 有效则继续
      └─ 不存在 → 停止,引导去 pacp-design-list
   b. 用户直接给了 spec 文件路径 → 读取,轻量校验
   c. 用户什么都没给 → 停止,提示:
      「需要先有规格文档。请用 pacp-design-list 生成。」

> [!note] 轻量校验
> 闸门只校验两段存在(元信息段存在、列定义段存在且非空),不校验段内细节。段内细节由 design 的质量门保障。
> 用户手写 spec(未经 design 质量门)直接喂给 build 时,提示「未经 design 质量门校验,可能有缺项」但不拦截。

关联表单的 templateId 解析(构建前置)

> [!important] list-spec「关联表单」字段填的是表单 spec 文件名,不是 templateId
> list-spec 元信息的「关联表单」字段填的是表单 spec 文件名(如 调查查询问通知书__表单),不是 templateId——设计阶段表单可能尚未构建、没有 templateId。build-list 构建前需解析出 templateId:
>
> 1. 读 .pacp/specs/动态渲染/{关联表单值}.md(如 调查询问通知书__表单.md)
> 2. 查找该 spec 的「## 构建记录」段,取 templateId
> ├─ 有构建记录 → 取 templateId,传入 --template-id
> └─ 无构建记录 → 停止,提示用户「关联表单尚未构建,请先用 pacp-build-form 构建 {文件名}」
> 3. 表单 spec 文件不存在 → 停止,提示文件名有误
>
> 这套机制让设计阶段(表单未构建)也能产出完整的列表 spec,把对 templateId 的依赖推迟到构建阶段——此时表单必然已构建。
> 「关联表单」字段为「无」时不解析,构建纯展示列表(LX=1)。

数据来源

  • 数据来源只有三个:① 远程 API(表结构、字段元数据、代码集)② 本 SKILL.md ③ 用户提供(spec 或列表 XH)。本地代码库里没有任何你需要的东西。

操作模式

  • 新增:用户提供 list-spec.md(或业务名),构建并提交新列表
  • 修改:用户提供列表 XH + 修改意图,按是否有 spec 分流(见上方入口分流)

重要约束:远程配置任务,不读任何源码(含当前项目)

> 本技能是在远程平台上创建/修改配置数据,不是在本地项目里开发代码。禁止读取任何源码——既包括本 Skill 的 lib/scripts,也包括当前项目(cwd)里的业务代码。

本 Skill 的 lib/、scripts/ 目录下的 .js 文件是运行时代码,由 execute_code 或 CLI node 命令通过 require() 加载执行。禁止使用 read_file、cat、search_files 等工具查看这些文件的内容——所有 API 签名、参数说明、示例代码都在本 SKILL.md 中,无需阅读源码实现。

行为约束

# 约束 说明
1 只用 CLI 命令操作 所有操作必须通过本 Skill 提供的 CLI 命令(list_creator.js)或 BwaiClient API 完成。禁止自行编写新脚本绕过 CLI。如果 CLI 报错,直接将错误信息报告给用户,不尝试自行修复或绕过
2 临时文件路径 所有生成的文件(JSON 配置、列对照表、探查结果、临时脚本)必须写入 .pacp/active/{业务名}_{时间戳}/ 工作区目录内。禁止在其他位置创建文件——包括子仓库根目录、当前工作目录、/tmp 等。CLI 的 --config 参数必须指向工作区内的文件路径
3 代码集必须用户指定 涉及公共代码集(commonCode)时,dmjbh(小写)必须由用户明确指定(spec 已填则用 spec 的,标「待定」则停下来问用户)。禁止 AI 根据字段语义自行推断代码集编号
4 SQL WHERE 默认 1=1 sqlWhere 默认使用 1=1(无过滤),除非用户明确要求加条件。禁止 AI 自行添加 SFYX = '1' 等过滤条件——不确定表中是否存在该列,随意添加会导致查询报错
5 SQL 方言敏感 sqlSelect / sqlWhere / sqlOrderBy 中的 SQL 必须使用标准通用写法(ANSI SQL)。如果必须使用数据库特有语法(如 LIMIT / TOP / ROWNUM),必须先明确目标数据库类型。非必要不使用特有语法
6 主动交互等待 需要用户确认或提供信息时,必须提供选项让用户选择,使用主动提问的方式让用户明确知道 AI 在等待输入。适用场景:代码集编号确认、数据库类型确认、有 spec 重建覆盖线上的确认等
7 缓存主动失效 CLI 会自动缓存表结构等查询结果(默认 7 天过期)。当 AI 执行了修改操作(新增/修改代码集、修改表结构等)后,应使用 --clear-cache --base-url <url> 清除对应缓存,确保后续查询拿到最新数据
8 Excel 导入后端资源禁止编造 接入 Excel 导入时(详见 references/excel-import-guide.md),jsonFilePath/importExcelService/templatePath 三项后端资源必须由用户提供,不生成后端代码、不推断 Service 类名、不编造 JSON/模板文件名

代码结构

本 Skill 由四个核心文件组成:

文件 职责
lib/bwai_client.js BwaiClient 类:HTTP 客户端、数据源探查(getTables/getColumns)、列表 CRUD API、工作区管理(.pacp/)、session 共享
scripts/col_widgets/ 自包含列组件目录(每个组件独立文件)
scripts/col_widgets/index.js 自动发现+注册中心(inferType/resolve/listTypes)
scripts/col_widgets/seq.js 序号列
scripts/col_widgets/checkbox.js 选择框列
scripts/col_widgets/operate.js 操作列
scripts/col_widgets/common_code.js 代码集列
scripts/col_widgets/default.js 普通数据列(含推断)
scripts/col_widgets/date_col.js 日期列(含推断)
scripts/list_builder.js 高级编排:createListConfig(client, opts) 构建并提交列表配置;associateForm(client, listXH, templateId, options) 关联动态表单
scripts/script_gen.js 脚本生成:dynamicFormScript(formId, pkField) 生成动态表单脚本

引入方式:

const { BwaiClient } = require('./lib/bwai_client');
const colWidgets = require('./scripts/col_widgets');
const { createListConfig, associateForm } = require('./scripts/list_builder');
const { dynamicFormScript } = require('./scripts/script_gen');

API 速查

require 引入

const { BwaiClient } = require('./lib/bwai_client');
const { makeColumn, makeQueryField, makeSeqColumn, makeOperateColumn,
        makeButton, makeCheckboxColumn, makeCommonCodeColumn,
        makeCodesetQueryField } = require('./scripts/col_widgets');
const { createListConfig, associateForm } = require('./scripts/list_builder');
const { dynamicFormScript } = require('./scripts/script_gen');

BwaiClient 方法

方法签名 返回值
new BwaiClient(baseUrl, sessionId) 客户端实例
await client.getTables() [{ TABLE_NAME, TABLE_COMMENT }]
await client.getColumns(tableName) [{ COLUMN_NAME, COLUMN_COMMENT, DATA_TYPE }]
await client.getPrimaryKey(tableName) 主键列名字符串
await client.getCommonCodeClassList({ pageSize: 10000 }) { list: [{ DMJBH, DMJMC }] }
await client.listQueryConfigs(page, size) { list: [{ XH, MC, PZLB, PZCX, JB, LX, ... }] }
await client.getQueryConfig(xh) 单条列表配置
await client.saveQueryConfig(opts) { XH, PZLB, PZCX, ... }
await client.deleteQueryConfig(xh) 删除结果
client.setTraceDir(dir) void
client._writeSummary(obj) void
BwaiClient.createWorkspace(name) 工作区绝对路径(基于 .pacp/active/)
BwaiClient.loadSession(baseUrl?) 读共享 JSESSIONID(.pacp/session.json,按 baseUrl 取,与 pacp-system-login 共享),无则 null
BwaiClient.saveSession(baseUrl, jsessionid, extra?) void

工厂方法速查

makeSeqColumn(displayName, index)
→ { name:'ROW_ID', type:'#XH', displayName, index, width:'4%', ... }

makeColumn(name, displayName, type?, index?, width?, isShow?, align?)
默认: type='string', index=1, width='10%', isShow=true, align='left'
→ { name, type, displayName, index, width, rowspan:1, colspan:1, isShow, events:{}, display:{align} }

makeCommonCodeColumn(name, displayName, dmjbh, index?, width?, align?)
默认: index=1, width='10%', align='center'
→ 同 makeColumn + display.type='COMMON_CODE', display.content.dmjbh

makeQueryField(name, title, dataType?, fieldType?, operate?, alias?, quickMatch?)
默认: dataType='string', fieldType='text', operate='LIKE', alias='', quickMatch=false
→ { name, dataType, title, type:fieldType, operate }

makeCodesetQueryField(name, title, dmjbh, opts?)
opts 默认: { dataType:'string', operate:'=', quickMatch:false, multi:false, alignType:'select', isEmpty:false, initValue:'' }
→ { name, dataType, title, type:'codeset', dataSourceType:'codeset', dmjbh, dm:'', fdm:'', multi, alignType, isEmpty, initValue }

makeButton(key, displayName, functionName)
→ { key, displayName, type:'normal', function }

makeOperateColumn(buttons, width?)
buttons: makeButton 返回值的数组
→ { name:'操作', type:'#CZL', display:{ type:'OPERATE_BTN', content:buttons } }

makeCheckboxColumn()
→ { name:'sjxzBtn', type:'#XZAN', displayName:'选择', index:1, width:'5%', ... }

dynamicFormScript(formId, pkField?)
pkField 默认: 'XH'
→ Vue 3 CRUD 脚本字符串(addClick/editClick/delRowClick/delClick)

createListConfig(client, opts)

字段           类型     必填  默认值           说明
title          string   是    -               列表标题(同时用作 MC)
sqlSelect      string   是    -               SQL 查询片段(不含 SELECT 关键字),如 'XH, MC FROM T_XXX'。支持多表 JOIN(见下方"多表联查")
columns        array    是    -               列定义数组
sqlWhere       string   否    '1=1'           WHERE 条件
sqlOrderBy     string   否    ''              ORDER BY
sqlGroupBy     string   否    ''              GROUP BY
queryFields    array    否    []              查询字段数组
quickMatch     array    否    []              快速匹配字段名数组
buttons        array    否    []              工具栏按钮
xh             string   否    ''              空=新增,非空=更新
jb/ys/tbxx/wbxx string  否    ''              脚本/样式/页头/页尾
mc             string   否    title           列表名称
sfyx           string   否    '1'             是否有效
lx             string   否    '1'             列表类型('1'=普通列表, '2'=选择器列表, '3'=动态表单。lx='2' 时自动注入选择列/按钮/脚本)

返回值:{ XH, PZLB, PZCX, ... }

associateForm(client, listXH, templateId, options?)

字段                  类型     必填  默认值  说明
primaryKey            string   否    -       主键字段名(空=用列表已有的)
injectButtons         bool     否    true    注入新增/删除按钮
injectOperateColumn   bool     否    true    注入操作列
injectCheckbox        bool     否    true    注入选择框
injectScript          bool     否    true    注入 CRUD 脚本

返回值:{ listXH, formTemplateId, primaryKey, listUrl, formUrl }

CLI 调用方式(推荐)

本 skill 提供命令行入口,无需编写 Node.js 脚本,通过 JSON 配置 + CLI 命令即可完成列表创建和表单关联。

> [!important] spec → list-config.json 的映射由 AI 在会话内完成
> 与 pacp-build-form 对称:list_creator.js 吃 list-config.json(不吃 list-spec.md)。AI 读 spec → 产出列对照表 field-mapping.md → 基于对照表产出 list-config.json → 喂给 list_creator.js。spec→config 的映射在会话内完成,保证过程可见、可审计。

前置条件

本 skill 需要 --session-id(即服务端的 JSESSIONID cookie)。

获取优先级(按顺序尝试,命中即停):

  1. 读 .pacp/session.json → 有效则直接复用
  2. 用户直接提供了 JSESSIONID → 直接使用
  3. 用户没提供 → 使用 pacp-system-login skill 获取(基于 chrome-devtools MCP)
  4. 获取失败 → 提示用户在浏览器手动登录后提供 JSESSIONID

> [!important] 登录强制 chrome-devtools MCP
> 获取 JSESSIONID 只接受两种方式(按优先级):用户直接提供 / 通过 pacp-system-login(内部基于 chrome-devtools MCP)。❌ 不接受 evaluate_script 读 cookie、手动猜测等不可靠方式。chrome-devtools MCP 不可用时,建议用户安装或直接提供 JSESSIONID。

命令格式

# 创建列表 + 关联表单(templateId 由 spec 关联表单字段解析得到)
node skills/pacp-build-list/scripts/list_creator.js \
  --base-url http://localhost:8080/basesystem \
  --session-id $SESSION_ID \
  --template-id <由关联表单 spec 构建记录解析> \
  --config list-config.json

# Step 1: 获取列索引(只有列名+注释,精简,用于补全 spec 字段名/核对列)
node skills/pacp-build-list/scripts/list_creator.js \
  --base-url http://localhost:8080/basesystem \
  --session-id $SESSION_ID \
  --check-only \
  --config - <<'EOF'
{"tableName": "T_HJJC_WTJCGZDJ"}
EOF
# → 返回 78 列的 name + comment + primaryKey

# 查看可用列组件类型
node skills/pacp-build-list/scripts/list_creator.js --list-types

参数说明

参数 必填 说明
--base-url 是 服务地址
--session-id 是 有效的 sessionId
--config 是 JSON 配置文件路径,传 "-" 从 stdin 读取
--template-id 否 表单 templateId(由 spec「关联表单」字段解析得到),提供则自动关联表单
--lx 否 列表类型:1=普通列表(默认), 2=选择器列表, 3=动态表单。也可在 JSON 配置中用 lx 字段指定
--xh 否 修改模式:指定列表 XH(优先级 --xh > config.xh > 空=新建)
--check-only 否 仅探查表结构不创建

JSON 配置格式(由 spec 映射产出)

{
  "title": "污染源委托监测登记",
  "tableName": "T_HJJC_WTJCGZDJ",
  "sqlSelect": "* FROM T_HJJC_WTJCGZDJ",
  "sqlWhere": "1=1",
  "sqlOrderBy": "",
  "primaryKey": "RWBH",
  "columns": [
    { "type": "seq", "displayName": "序号" },
    { "name": "RWBH", "displayName": "任务编号", "width": "15%" },
    { "name": "SJCDWMC", "displayName": "受监测单位名称", "width": "20%" },
    { "name": "JCLB", "displayName": "监测类别", "type": "commonCode", "dmjbh": "DMJ_XX" },
    { "type": "operate", "width": "12%", "buttons": [
        { "key": "add", "displayName": "新增", "function": "addClick" },
        { "key": "edit", "displayName": "编辑", "function": "editClick" },
        { "key": "delete", "displayName": "删除", "function": "delRowClick" }
    ]}
  ],
  "queryFields": [
    { "name": "RWBH", "title": "任务编号", "operate": "LIKE", "quickMatch": true },
    { "name": "JCLB", "title": "监测类别", "type": "codeset", "dmjbh": "DMJ_XX" }
  ],
  "quickMatch": ["RWBH", "SJCDWMC"],
  "associateForm": true
}

字段说明:
- title/tableName: 必填,sqlSelect 默认 "* FROM {tableName}"
- columns[].type: seq(序号) / checkbox(选择框) / operate(操作列) / commonCode(代码集列) / 其他(普通列)
- columns[].colType: 可省略,CLI 根据 DATA_TYPE 自动推断:datetime→date, decimal/int→number, 其他→string。只有需要覆盖推断结果时才显式指定。
- columns[].name: 字段名(所有列必需。seq 列用 makeSeqColumn() 自动处理;operate 列用 makeOperateColumn() 自动填充 name:'操作';手动构建 JSON 时需填 name)
- columns[].width: 列宽,如 "15%"。可省略,AI 应根据列名汉字数自动估算宽度,参考规则:2字以内(序号、操作)→ 5%;3-4字(行业类型)→ 8%;5字(排放口总数)→ 9%;6字(超标排放口数)→ 10%;长文本列(单位名称)→ 18-20%;日期时间列 → 12%;编号/编码列 → 13-15%。总宽度约等于 100%
- columns[].dmjbh: commonCode 类型的代码集编号
- columns[].buttons[].key/displayName/function: 操作按钮定义
- queryFields[].type: codeset(代码集下拉) / 其他(普通文本)
- queryFields[].dmjbh: codeset 类型的代码集编号
- queryFields[].quickMatch: boolean
- quickMatch: 快速匹配字段名数组
- associateForm: boolean,配合 --template-id 自动关联
- primaryKey: 用于 associateForm,空=自动获取

多表联查(JOIN)

> [!important] 多表 JOIN 由 spec「关联关系」驱动拼接
> spec 不写 SQL 语句,但元信息记录了「主表 + 关联表 + 关联关系(字段对应)」。build 据此拼 JOIN:
> - 单表字段 → sqlSelect 直接写 字段名
> - 多表字段 → sqlSelect 写 别名.字段名,表别名由 build 自动派生(如 T_ZF_AJ→a,T_ZF_JCJL→b)
> - ON 条件 → 取自 spec 关联关系的字段对应(如 T_ZF_JCJL.AJ_XH → T_ZF_AJ.XH → ON b.AJ_XH = a.XH)
> - 关联关系缺失 → 停止并询问用户(不靠命名猜测)

sqlSelect 支持标准 SQL JOIN 语法。tableName 填主表名(用于列元数据推断),sqlSelect 用 JOIN 引入其他表。

{
  "title": "执法案件列表",
  "tableName": "T_ZF_AJ",
  "sqlSelect": "a.XH, a.AJBH, a.AJMC, a.LARQ, b.JCRQ AS LATEST_JCRQ, b.JCRY AS LATEST_JCRY FROM T_ZF_AJ a LEFT JOIN T_ZF_JCJL b ON a.XH = b.AJBH AND b.JCRQ = (SELECT MAX(JCRQ) FROM T_ZF_JCJL WHERE AJBH = a.XH)",
  "sqlWhere": "1=1",
  "sqlOrderBy": "a.LARQ DESC",
  "columns": [
    { "type": "seq", "displayName": "序号" },
    { "name": "AJBH", "displayName": "案件编号", "width": "15%" },
    { "name": "AJMC", "displayName": "案件名称", "width": "20%" },
    { "name": "LATEST_JCRQ", "displayName": "最新检查日期", "colType": "date", "width": "15%" },
    { "name": "LATEST_JCRY", "displayName": "最新检查人员", "width": "15%" }
  ]
}

注意事项:
- sqlSelect 不含 SELECT 关键字,直接写列名+FROM(CLI 会自动去掉多余的 SELECT)
- columns[].name 必须与 sqlSelect 中的列名一致(含别名)
- JOIN 查询中使用了表别名时,columns[].name 应使用最终列名(别名或原列名)
- tableName 仍然填主表名,用于 CLI 的列元数据推断;JOIN 的子表列需要用 colType 显式指定类型
- sqlWhere 中可以引用别名,如 a.LARQ >= '2024-01-01'
- SQL 方言:示例中的 LEFT JOIN + MAX() 子查询是 ANSI SQL 通用写法,适用于所有数据库。如需使用方言特有语法(如 LIMIT / TOP / ROWNUM),必须先确认目标数据库类型(见行为约束 #5)

聚合查询(SUM/COUNT + GROUP BY)

当列表需要显示汇总数据(如总金额、明细笔数),使用聚合查询:

{
  "title": "项目经费列表",
  "tableName": "T_XMJF_SP",
  "sqlSelect": "a.XH, a.XMBH, a.XMMC, SUM(b.JE) AS TOTAL_JE, COUNT(b.XH) AS MX_COUNT FROM T_XMJF_SP a LEFT JOIN T_XMJF_MX b ON a.XH = b.XMH",
  "sqlGroupBy": "a.XH, a.XMBH, a.XMMC",
  "sqlWhere": "1=1",
  "sqlOrderBy": "a.XMBH",
  "columns": [
    { "name": "XMBH", "displayName": "项目编号", "width": "15%" },
    { "name": "XMMC", "displayName": "项目名称", "width": "20%" },
    { "name": "TOTAL_JE", "displayName": "总金额", "colType": "number", "width": "10%" },
    { "name": "MX_COUNT", "displayName": "明细笔数", "colType": "number", "width": "10%" }
  ]
}

注意事项:
- 聚合列(SUM/COUNT/MAX 等)必须用 AS 别名,columns[].name 对应别名
- sqlGroupBy 必须包含所有非聚合列(主表的字段都要写进去)
- 聚合列需要用 colType 显式指定类型(CLI 无法从 sqlSelect 自动推断)
- tableName 仍填主表名

输出格式(JSON 到 stdout)

创建列表 成功:

{
  "success": true,
  "listXH": "178074...",
  "title": "xxx",
  "columnCount": 10,
  "queryFieldCount": 2,
  "listUrl": "http://...basesystem/app/index.html#/list-render/xxx",
  "associatedForm": true,
  "formUrl": "http://...basesystem/app/index.html#/form-render/xxx",
  "templateId": "xxx",
  "primaryKey": "RWBH"
}

check-only Step 1(不带 config.columns):

{
  "success": true,
  "mode": "check-only-index",
  "tableName": "T_HJJC_WTJCGZDJ",
  "primaryKey": "RWBH",
  "columns": [
    { "name": "RWBH", "comment": "任务编号" },
    { "name": "SJCDWMC", "comment": "受监测单位名称" }
  ],
  "columnCount": 78
}

check-only Step 2(带 config.columns 白名单):

{
  "success": true,
  "mode": "check-only-detail",
  "tableName": "T_HJJC_WTJCGZDJ",
  "primaryKey": "RWBH",
  "columns": [
    { "name": "RWBH", "comment": "任务编号", "dataType": "varchar", "typeCategory": "string" },
    { "name": "NCYJCRQ", "comment": "拟采样监测日期", "dataType": "datetime", "typeCategory": "date" }
  ],
  "columnCount": 9,
  "existingListCount": 15
}

失败:

{ "success": false, "error": "错误信息" }

进度信息输出到 stderr,不污染 stdout 的 JSON。

处理流程:spec 驱动(新增)+ XH 驱动(修改)

入口分流已在上方「入口分流 + 文件存在性闸门」定义。以下为两条入口的具体执行流程。

新增入口:spec 驱动

阶段0 文件存在性闸门 → 阶段1 登录+工作区 → 阶段2 [按需]探查列/代码集 → 阶段3 spec→config 列对照表 + 构建 JSON → 阶段4 提交 + spec 回写 → 阶段5 端到端验证

阶段0 文件存在性闸门

见上方「入口分流 + 文件存在性闸门」。按优先级查找 list-spec 文件(.pacp/specs/动态渲染/{业务名}__列表.md 优先),轻量校验两段存在。

阶段1 登录前置 + 工作区初始化

> 🔴 登录是第一件事:先读 .pacp/session.json 复用;无缓存或过期则通过 pacp-system-login skill 取 JSESSIONID。

登录完成后,从 spec 元信息提取业务名,在 .pacp/active/ 下创建工作区子目录:

const workspace = path.join(process.cwd(), '.pacp', 'active', businessName + '_' + timestamp);
fs.mkdirSync(workspace, { recursive: true });

创建 BwaiClient 实例后,立即开启请求追踪:

const { BwaiClient } = require('./lib/bwai_client');
const client = new BwaiClient(BASE_URL, SESSION_ID);
client.setTraceDir(workspace);
// 之后所有 API 调用的请求/响应自动记录到 workspace/api-trace.jsonl
// 高级方法(createListConfig/associateForm)的入参出参记录到 workspace/trace-summary.jsonl

阶段2 [按需] 探查列/代码集

> 按需执行:仅当 spec 字段需核对列细节、代码集字段标了「待定」、或多表联查需确认关联表列时才执行。

使用 lib/bwai_client.js 的 BwaiClient 类探查:

// 主表列(用于核对 spec 字段名、补全列类型)
const columns = await client.getColumns(spec.主表);
// 多表联查时,关联表的列也需探查(核对来源表字段名)
if (spec.关联表) {
  for (const t of spec.关联表) {
    await client.getColumns(t);
  }
}

> [!important] 阶段2 探查时遇到"代码集编号:待定"的处理
> spec 里标"待定"的代码集列/查询条件,停下来问用户要 dmjbh 编号(保持"代码集必须用户给,AI 不猜"铁律)。
> - 用户给了编号 → 核对编号存在性(可查 ggdmz/list)→ 回填 spec → 继续
> - 用户给不出 → 字段先按普通文本列构建,构建后提醒用户自行配置代码集

将列信息和代码集核验结果保存到工作区 table-info.md。

阶段3 spec → config 列对照表 + 构建 JSON

> [!important] 前置步骤:spec→config 逐列对照(强制)
> 构建 JSON 前,必须先产出一份列对照表,写在工作区 .pacp/active/{任务}/field-mapping.md:
>
> | spec 列 | 来源表 | 列类型 | →组件 | 宽度语义 | →width | 代码集 | 备注 |
> |---------|--------|--------|-------|---------|--------|--------|------|
> | AJBH 案件编号 | T_ZF_AJ | 普通文本 | default | 窄 | 10% | - | - |
> | JCRQ 检查日期 | T_ZF_JCJL | 日期 | date | 日期 | 12% | - | JOIN来源 |
> | AJLB 案件类别 | T_ZF_AJ | 代码集 | commonCode | 窄 | 10% | DMJ_AJLB | - |
> | [序号] | - | 序号 | seq | 序号 | 5% | - | 系统列 |
> | [选择框] | - | 选择框 | checkbox | 选择框 | 5% | - | 系统列 |
> | [操作] | - | 操作 | operate | 操作 | 12% | - | 系统列 |
>
> 强制要求:
> - 每个 spec 数据列 + 系统列必须出现在对照表中(不允许遗漏)
> - width 值必须显式写出,标注来源(spec 列定义的宽度语义行),不允许使用默认值
> - 多表联查列必须标注「来源表」和 JOIN 来源
> - 代码集列必须写出 dmjbh(spec 已填或阶段2 回填)
>
> 目的:构建过程可见、可审计。产物列不对时,对照表能快速定位是 spec 写错还是 build 映射错。

列词汇 → 组件映射(spec 驱动构建的核心):

spec 列词汇 → CLI columns[].type 说明
普通文本 (省略,走 default 推断) 普通数据列
数字 (省略,colType=number) 数值列
日期 (colType=date) 日期列
长文本 (省略,走 default) 长文本列
代码集 commonCode + dmjbh 代码值翻译列
序号 seq 系统列
选择框 checkbox 系统列
操作 operate + buttons 系统列
⚠️自定义 AI 自行决定(兜底) 映射不到时

宽度语义 → width 映射:

spec 宽度语义 → width
窄 10%
中 15%
宽 20%
日期 12%
操作 12%
序号 5%
选择框 5%

查询条件词汇 → queryFields 映射:

spec 输入类型 → queryFields[].type 操作符
普通文本 (省略,走 text) LIKE
下拉(代码集) codeset + dmjbh =
下拉(静态枚举) (省略,走 text 或 select) =
日期区间 (type=text, operate=RANGE) RANGE
代码集 codeset + dmjbh =

> [!important] 系统列机制:spec 声明 → config 显式 → associateForm 让位
> 序号/选择框/操作三列由 design-list 强制写进 spec(用户可控是否显示、宽度)。build 映射时把系统列写进 list-config.json 的 columns,由 col_widgets 工厂处理:
> - width 读 config 覆盖默认:seq/checkbox/operate factory 读 col.width,默认值统一对齐宽度语义词汇表(序号 5% / 选择框 5% / 操作 12%)
> - name 由 factory 自动补全(seq→ROW_ID / checkbox→sjxzBtn / operate→操作),config 无需显式写 name(type_check 已对系统列放宽 name 校验,seq 列只写 {type:"seq"} 不会报错)
> - isShow 读 config:spec 某系统列「显示:否」→ config 该列 isShow:false
> - associateForm 不覆盖 config 声明的系统列:config 已有 #CZL 操作列 / #XZAN 选择框列时保留不注入;仅 config 无对应列时才兜底注入默认列
>
> 一致性自检:构建前 field-mapping.md 列对照表标注的每个系统列 width,必须在 list-config.json 对应列体现(显式 width 或确认走默认)——对照表与 config 不一致即修正 config,保证对照表可审计。

基于对照表产出 list-config.json(写入工作区),然后喂给 list_creator.js。

阶段4 提交 + spec 回写

提交成功后,打开列表页面让用户自行查看:

  1. 打开列表页(两步导航,见下方刷新策略):先导航到中转页,再进 list-render/{listXH}。若无浏览器工具,把 URL 给用户自行打开。
  2. 告知用户:「列表已提交并在浏览器打开,请查看渲染是否正常。有问题告诉我,没问题即可。」
  3. 等用户反馈:不主动做快照验证、不自动修复。

> [!important] 浏览器预览刷新策略(Vue Router hash 模式)
> 平台前端用 Vue Router hash 模式。直接从 list-render/A 改 URL 到 list-render/B,Vue Router 检测到"同组件 param 变化",不触发组件重载。
> 正确操作(两步导航):先导航到中转页(任何非 list-render 的页面)→ 再导航到 #/list-render/{listXH}。

> [!important] spec 回写(闭环)
> 提交成功后,向 spec 回写事实信息(不回写组件/width 等实现细节,保持 spec 纯需求层):
>
> 回写内容:
> | 回写项 | 写在哪 |
> |--------|--------|
> | 列表 XH + listUrl(访问地址)+ 构建时间 | spec 末尾的 ## 构建记录 段(design-list 落盘时留空,build 回填) |
> | 关联表单 templateId(构建时解析得到) | 构建记录段的「关联表单 templateId」行 |
> | 代码集编号(spec 标「待定」→ build 问到后填入) | 列定义对应列的「代码集编号」行(待定 → 实际编号) |
>
> 示例——spec 末尾的构建记录段:
> markdown > ## 构建记录 > - 列表 XH:1780749234641011735040 > - 构建时间:2026-07-15T15:30:00 > - 关联表单 templateId:13f56f3f-9f10-4ad3-bbf3-cf55c49e5c42 > - 备注:首次构建 >
>
> 不回写的:组件映射(commonCode/seq 等)、width 值、列顺序——这些是实现细节,回写会污染 spec 的纯需求语义。

阶段5 端到端验证

提交成功后,验证列表页面渲染是否正常:

🔴 验证不通过时必须报告用户 — 自动修复最多重试 2 次,超过后必须停止并报告。

验证内容:页面正常加载、列表数据正常加载(表头行 + 无 SQL 报错弹窗)、控制台无 JS 错误。

实现方式:使用浏览器工具(chrome-devtools MCP)打开 list-render/{XH} URL 验证;无浏览器工具则提示用户手动打开列表 URL 确认。

验证失败处理:AI 可定位根因(如 SQL 方言错误、字段属性配置错误)→ 自动修复配置并重新提交 → 再次验证;AI 无法判断 → 截图或错误信息报告用户;自动修复最多重试 2 次,超过后报告用户,不进入无限循环。

> [!note] 列表渲染路由需要菜单权限
> /#/list-render/{xh} 直接访问可能 404(需菜单注册)。验证时如遇 404,提示用户通过菜单进入或先注册菜单权限(见已知陷阱 #8)。

修改入口:XH 驱动(按有无 spec 分流)

getQueryConfig(XH) / 读 spec → 推断改动并生成 diff → 用户确认 → 提交

分流逻辑(见上方入口分流):
- 有 spec(扫描 .pacp/specs/动态渲染/*__列表.md 构建记录段命中该 XH)→ 改 spec → 重新构建覆盖线上(保持 spec 与线上一致)。⚠️ 若线上曾被手工改过,重建前提示用户确认。
- 无 spec(无任何 list-spec 构建记录匹配)→ getQueryConfig(xh) 拉线上配置 → 解析 PZLB/PZCX → 对比变更(diff 分析)→ 确认摘要高亮变更(🟢新增/🔴删除/🟡修改)→ 提交(不回写 spec)。可提示用户用 design-list 补 spec 以便后续复用。

详见下方「修改模式」章节。

数据结构

PZLB(列表配置)

{
  "targeDatatType": "sql|table|view|form|dataService",
  "targetData": {
    "dataSource": "jdbc/default",
    "select": "SQL 片段或表名",
    "where": "WHERE 条件",
    "groupBy": "GROUP BY",
    "orderBy": "ORDER BY"
  },
  "isShowSeq": true,
  "isShowCheck": true,
  "isPageable": true,
  "isShowTitle": true,
  "titleName": "列表标题",
  "pageSize": 20,
  "buttons": [],
  "columns": [{ "name", "type", "displayName", "index", "width", "isShow", "events", "display" }]
}

PZCX(查询配置)

{
  "quickMatch": ["FIELD1", "FIELD2"],
  "queryField": [{ "name", "dataType", "title", "type", "operate", "alias?", "quickMatch?" }]
}

列宽规范

列宽通过 width 字段控制(百分比字符串),影响列表各列的显示宽度。

列类型 推荐宽度 说明
序号列(type: 'seq') 5% 固定窄列
选择框列(自动注入) 5% 固定窄列
操作列(type: 'operate') 12% 编辑+删除两个按钮
短文本列(编号、代码、类别) 10% 单词/短语级内容
中等文本列(名称、标题) 15% 2-4 个汉字
长文本列(描述、备注、地址) 20% 长文本内容
日期列 12% yyyy-MM-dd 格式

原则:
- 所有列 width 之和不应超过 100%(选择框和序号已占 10%)
- 列顺序:选择框 → 序号 → 数据列 → 操作列(操作列始终放在最后一列)

列类型

运行 node list_creator.js --list-types 查看所有可用列组件类型和配置示例。

格式渲染类型(display.type)

列的 display 对象包含 type 和 content 字段,控制列的渲染方式:

display.type display.content 类型 说明
'' 或未设置 任意 无格式渲染(默认)
USER boolean 人员类型(content=true 显示全称)
DEPT boolean 部门类型
HYLX boolean 行业类型
DATE { format: 'yyyy-MM-dd' } 日期类型
COMMON_CODE { dmjbh: 'DMJ_XXX' } 公共代码值(⚠️ 小写 dmjbh)
CUSTOM_CODE { ... } 自定义代码(后续支持)
XZQY { SHENG, SHI, QU, JD } 行政区域
HTML string 列模板 HTML
OPERATE_BTN Array<{ key, displayName, function, type }> 操作按钮
OTHER_DATA 任意 其他数据

> ⚠️ display.content.dmjbh 中的 dmjbh 是小写,与后端 API 参数 DMJBH(大写)不同,不要混用。

查询控件类型

type 说明 适用 dataType
text 文本输入(默认) string
date 日期选择器 date
codeset 代码集下拉 string
user 用户选择器 string
dept 部门选择器 string

codeset 查询条件扩展字段

当 type='codeset' 时,查询字段对象包含以下额外字段:

字段 必填 默认 说明
dataSourceType 是 — 'codeset'(本次只支持 codeset)
dmjbh 必填 — 公共代码集编号
dm 否 '' 代码值过滤
fdm 否 '' 父代码值过滤(树形代码集)
multi 否 false 是否多选
alignType 否 'select' 'tag' / 'select' / 'radio' / 'checkbox'
isEmpty 否 false 是否显示空值选项
initValue 否 '' 默认值(代码值 DM)

查询操作符

操作符 说明
LIKE 模糊匹配
= 精确匹配
RANGE 范围(日期、数字)

脚本类型

字段 说明
JB JavaScript 生命周期回调 + 按钮事件
YS CSS 样式
TBXX 页头 HTML
WBXX 页尾 HTML

修改模式

修改入口按「是否有 spec」分流(决策记录⑥):

方式一:有 spec → 改 spec → 重新构建覆盖线上

当列表 XH 能在某个 list-spec 的「## 构建记录」段反查到时,保持 spec 与线上一致:

  1. 读 spec(.pacp/specs/动态渲染/{业务名}__列表.md)
  2. 按用户修改意图改 spec(如加列、改查询条件)
  3. ⚠️ 若线上曾被手工改过(绕过 spec),重建前提示用户确认「重建会用 spec 覆盖线上手工改动」
  4. 走新增入口的 spec 驱动流程构建,提交时传入已有 XH(覆盖更新)
  5. spec 回写更新构建记录

方式二:无 spec → 直改线上配置,不回写 spec

当列表 XH 在任何 list-spec 构建记录都反查不到时(历史/别处创建的列表):

  1. 用 client.getQueryConfig(xh) 或 client.listQueryConfigs() 获取现有配置
  2. 解析 PZLB/PZCX JSON
  3. 对比变更(diff 分析)
  4. 确认摘要高亮变更(🟢新增/🔴删除/🟡修改)
  5. 提交时传入已有的 XH(覆盖更新),不回写 spec
  6. 可提示用户「此列表无 spec,可用 pacp-design-list 补一份 spec 以便后续复用」

传入 XH 的三种方式

方式一:CLI --xh 参数(推荐)

node list_creator.js \
  --base-url http://host:port/contextPath \
  --session-id $SESSION_ID \
  --xh 1781077346641011735040 \
  --template-id FORM_TEMPLATE_XH \
  --config list-config.json

方式二:JSON 配置中写 xh

{
  "xh": "1781077346641011735040",
  "title": "...",
  "...": "..."
}

方式三:编程 API

const result = await createListConfig(client, {
  // ... 同新增的参数
  xh: existingXH,   // 传入已有 XH 进入更新模式
});

> 优先级:--xh 命令行参数 > config.xh JSON 字段 > 空(新建)

表单关联(可选)

如果 spec 元信息「关联表单」字段有值(非「无」),需要关联动态表单(列表升级为 LX=3,支持增删改)。

前置:解析 templateId

按上方「关联表单的 templateId 解析」章节,读表单 spec 的构建记录段取 templateId。表单未构建则停止提示用户先构建。

调用 associateForm

使用 associateForm(client, listXH, templateId, options) 关联列表与表单:

// listXH 来自 createListConfig() 的返回值
// templateId 来自关联表单 spec 的构建记录段
const assocResult = await associateForm(client, listXH, templateId, {
  primaryKey: 'XH',  // 可选:主键字段名(spec 元信息「主键」)
  // 以下默认为 true,用户要求关闭时设为 false:
  // injectButtons: true,        // 工具栏新增/删除按钮
  // injectOperateColumn: true,  // 行内编辑/删除按钮
  // injectCheckbox: true,       // 选择框列
  // injectScript: true,         // 动态表单脚本
});
// assocResult.listUrl, assocResult.formUrl

> [!important] 系统列注入与 config 声明的关系(自动让位,无需手动关闭)
> associateForm 会自动识别 config 已声明的系统列:config 已有 #CZL 操作列或 #XZAN 选择框列时,保留 config 的、不重复注入(含其自定义 width/按钮)。因此 spec 声明的系统列写进 config 后,associateForm 自动让位,无需手动设 injectOperateColumn: false / injectCheckbox: false。仅当 config 完全没声明对应系统列时,associateForm 才兜底注入默认列。

LX 类型说明

LX 值 说明 使用场景
'1' 普通列表(默认) 纯数据展示,无表单操作
'2' 选择器列表 弹窗选择场景:列表渲染为对话框,用户勾选行后通过确定/清除/关闭按钮交互
'3' 动态表单模式 列表+表单联动,支持增删改(associateForm 自动升级到此)

选择器列表(LX=2)

用于弹窗选择场景(如选择人员、选择部门、选择关联记录)。列表渲染为对话框,用户勾选行后通过确定/清除/关闭按钮与父组件交互。

创建方式:createListConfig(client, { lx: '2', ... }),或 CLI --lx 2,或 JSON 配置 "lx": "2"。

自动注入(调用方无需手动配置):
- columns 头部注入 #XZAN 类型选择列(不要额外设 isShowSelect=true,否则会重复渲染选择列)
- pzlb.buttons — 注入三个标准按钮:确定(confirmClick)、清除(clearClick)、关闭(closeClick)
- JB 脚本 — 默认实现三个函数(平台「#24 动态数据选择器」规范,JB 必须用 return {...} 对象包裹)

⚠️ 三按钮不可缺失(必要条件):选择器列表必须含「确定(confirmClick)、清除(clearClick)、关闭(closeClick)」三按钮及对应 JB 函数。

约束:
- 不传 buttons/jb → createListConfig 自动注入三按钮和脚本(推荐)
- 自定义 buttons(非空数组)→ 不覆盖,但调用方必须自行包含这三个按钮
- 自定义 jb → 不覆盖,但调用方必须自行实现上述三个函数
- 选择器列表不应再调用 associateForm()(LX=2 与 LX=3 互斥)

Excel 导入接入(按需加载)

用户要求列表支持「导入 Excel / 批量导入」时,动态列表运行时已内置 openImportDialog / downloadImportTemplate 能力,只需配置工具栏按钮 + JB 脚本即可接入。

> 硬约束:Excel 导入的后端三件套(importExcelService 业务 Service 类名 / jsonFilePath 列映射 JSON / templatePath xlsx 模板)必须由用户明确提供,AI 禁止编造。若用户未提供,必须主动询问。

按需加载:涉及 Excel 导入配置时,必须先加载 references/excel-import-guide.md 获取完整的触发词识别、后端三件套索取规范、按钮配置、JB 脚本模板、参数说明、完整示例和常见问题排查。

5.x 平台知识权威源(必读)

> 涉及以下主题时,优先加载 pacp-dynamic-wiki skill 的 references(本 skill 自带的 list-script-guide.md 为兜底副本):
>
> - 列表脚本写法(ScriptContext API、CRUD 四函数、选择器三按钮、openFormDialog 参数、jsTools 约束)→ wiki 的 5x/list-script-guide.md
> - 列表渲染契约(display.type、查询字段类型、列宽规范、LX 类型机制)→ wiki 的 5x/list-render-contract.md
> - 平台 API 端点(datasources/tables/dynamicqueryforconfig/...)→ wiki 的 5x/platform-api-endpoints.md
> - 平台数据结构(PZLB/PZCX/Template JSON/MODELJSON)→ wiki 的 5x/platform-data-structures.md
> - 平台机制(LX=2 选择器自动注入、关联表单、多表 JOIN)→ wiki 的 5x/platform-mechanisms.md
> - 平台陷阱(tempateId 拼写、_ELEMENT 后缀、getcloumninfo 小写、SQL 方言)→ wiki 的 5x/platform-pitfalls.md
> - Preview 渲染规范(--preview 输出格式)→ wiki 的 5x/preview-mode-design.md
>
> ZCode 会根据 description 自动触发 wiki skill(progressive disclosure)。
> 如未自动触发,AI 应主动通过 Skill 工具调用 pacp-dynamic-wiki。
>
> 5.x 平台升级时,wiki skill 是单一同步点,本 skill 不再单独维护这些知识。

API 端点(已验证 ✅)

端点 方法 说明 验证
/api/v2/platform/database/datasources POST 数据源列表 ✅
/api/v2/platform/database/tables POST 表列表 ✅
/api/.../getcloumninfo POST 列信息(tablename 小写) ✅
/api/.../dynamicqueryforconfig POST 执行 SQL 获取字段 ✅
/api/.../getformconfig POST 查询列表配置列表 ✅
/api/.../getDynamicQueryPzByXh GET 按 XH 获取配置 ✅
/api/.../saveformconfig POST 保存列表配置 ✅
/api/.../deldynamicqueryinfo POST 删除列表配置 ✅
/api/v2/platform/system/commoncode/ggdmj/query POST 公共代码集分页查询 ✅
/api/v2/platform/system/commoncode/ggdmz/query POST 公共代码值分页查询 ✅
/api/v2/platform/system/commoncode/ggdmz/list POST 公共代码值列表(不分页) ✅

> /api/.../ 是 /api/v2/common/component/queryservice/design/controller/dynamicquerycontroller/ 的缩写

认证

通过 --session-id 传入有效的 sessionId(优先读 .pacp/session.json 复用)。Session 过期时(401),提示用户提供新 sessionId。

错误处理

  • Session 过期(401):提示用户提供新 Session
  • 业务错误(500 errorCode):分析错误信息,修正后重试
  • 列信息为空:提示用户确认表名是否正确

工作区文件

文件 用途
api-trace.jsonl 所有 API 请求/响应的完整追踪(每行一个 JSON,含请求体、响应体、耗时)
trace-summary.jsonl 高级方法(createListConfig/associateForm)的结构化入参/出参摘要
table-info.md 数据表结构信息
field-mapping.md spec→config 列对照表(构建前置产物)
list-config.json 从 spec 映射出的构建配置(喂给 list_creator.js)
existing-list.json 已有配置(修改模式)

⚠️ 已知陷阱(必读)

以下陷阱均来自实际调试中遇到的血泪教训。创建列表前必须逐条检查。

# 陷阱 正确做法 症状
1 MC 字段缺失 saveQueryConfig 必须传入 MC(列表名称),否则前端不显示 保存成功但设计列表页搜不到
2 SFYX 未设为 1 SFYX: '1' 表示有效,'0' 或缺失 = 隐藏 列表存在但前端不可见
3 LX 未设置 LX: '1' 表示普通列表,'0' 或缺失 = 类型异常 列表类型显示为空
4 getcloumninfo 参数大小写 参数名是全小写 tablename,不是 tableName API 调用失败
5 列名与数据库不一致 makeColumn 的 name 必须与 SELECT 中的列名一致 列表渲染时该列无数据
6 tempateId 拼写(表单关联时) 后端字段名是 tempateId(少一个 l) 空字符串 → 错误码 120340
7 attrbutevalues 直接格式 属性是直接键值对 {FIELD: 'xxx'},不是 {FIELD: {value: 'xxx'}} 后端解析异常
8 列表渲染路由需要菜单权限 /#/list-render/{xh} 需要菜单注册才能直接访问 直接 URL 访问 404
9 dmjbh 大小写 display.content 中是小写 dmjbh,后端 API 参数是大写 DMJBH 列渲染失败或代码值查询为空
10 codeset operate 默认值 codeset 查询条件 operate 默认 '='(精确匹配),不是 'LIKE' 下拉筛选结果不正确
11 sqlWhere 禁止加 SFYX 表中可能没有 SFYX 列,sqlWhere 必须默认 1=1,禁止自行添加 SFYX = '1' 查询报错"字段不存在"
12 associateForm 的 listXH 无效 调用前确认 createListConfig 返回了有效的 XH associateForm 报错 "找不到列表"
13 数据库方言错误 SELECT TOP n 是 SQL Server,LIMIT n 是 MySQL/PostgreSQL,ROWNUM <= n 是 Oracle。未确认数据库类型前禁止使用任何方言特有语法,必须用 ANSI SQL 通用写法(如 LEFT JOIN + MAX() 子查询替代 LIMIT 1) 列表查询报错 SQLSyntaxErrorException
14 选择器列表(LX=2)缺三按钮 LX=2 必须有确定(confirmClick)/清除(clearClick)/关闭(closeClick)三按钮及对应 JB 函数;走默认流程会自动注入,但自定义 buttons 时也必须包含这三个(function 名必须对应) 弹窗能打开却无法确认/清除/关闭,选择器不可用

跨 Skill 协作

与 pacp-design-list 联动(新增入口)

用户:"帮我设计/做一个 XX 列表"
  ↓
1. 先执行 pacp-design-list → 产出 list-spec.md(.pacp/specs/动态渲染/{业务名}__列表.md)
  ↓
2. 再执行 pacp-build-list(本 skill)→ 读 spec → 列对照表 → list-config.json → 构建 → spec 回写

与 pacp-build-form 联动(关联表单)

列表的 spec「关联表单」字段填表单 spec 文件名。build-list 构建前读表单 spec 的构建记录段取 templateId。完整 CRUD 流程:

用户:"帮我做 XX 的增删改查(表单+列表)"
  ↓
1. pacp-design-form → 产出 {业务名}__表单.md
2. pacp-build-form → 构建 → 回写表单 spec 的「构建记录」段(含 templateId)
3. pacp-design-list → 产出 {业务名}__列表.md(关联表单字段填 {业务名}__表单)
4. pacp-build-list(本 skill)→ 读列表 spec → 解析关联表单 templateId → 构建 + associateForm → 回写列表 spec 的构建记录段

两个 skill 的 BwaiClient 是独立的,方法集不同,必须各自创建各自的实例,不可共享。但两个 CLI 共用同一个 session-id(.pacp/session.json)。

// ─── 各自引入各自的模块 ───────────────────────────────────
const { BwaiClient: FormClient } = require('./skills/pacp-build-form/lib/bwai_client');
const { createFormConfig } = require('./skills/pacp-build-form/scripts/form_builder');

const { BwaiClient: ListClient } = require('./skills/pacp-build-list/lib/bwai_client');
const { createListConfig, associateForm } = require('./skills/pacp-build-list/scripts/list_builder');

// ─── 各自创建各自的 client,使用同一个 sessionId ──────────
const fClient = new FormClient(baseUrl, SESSION_ID);
const lClient = new ListClient(baseUrl, SESSION_ID);

⚠️ 关键约束:fClient 和 lClient 是不同类的实例,方法集不同,不可混用(fClient 有 saveForm 没 saveQueryConfig,lClient 有 saveQueryConfig 没 saveForm)。

完整 CRUD 流程(CLI 方式)

# 第1步:构建表单(pacp-build-form),其 templateId 会回写到 {业务名}__表单.md 的构建记录段
node skills/pacp-build-form/scripts/form_creator.js \
  --base-url http://localhost:8080/basesystem \
  --session-id $SESSION_ID \
  --config form-config.json

# 第2步:构建列表 + 关联表单(templateId 从列表 spec 的关联表单字段解析,或手动传)
node skills/pacp-build-list/scripts/list_creator.js \
  --base-url http://localhost:8080/basesystem \
  --session-id $SESSION_ID \
  --template-id "$TEMPLATE_ID" \
  --config list-config.json

常见问题

5 问
答案由本站依据条目字段整理
构建与修改动态列表配置怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_ee9b2ae1/pacp-build-list。安装方式为未标注。装完刷新技能列表或重开客户端。

构建与修改动态列表配置支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

构建与修改动态列表配置权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

构建与修改动态列表配置收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

构建与修改动态列表配置用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 2026-11-06。