# 查询体验重构实施计划 ## 1. 重构目标 本次重构的目标不是增加查询表达力,而是缩短业务人员从“知道要找什么”到“看到结果”的路径。 重构后,列表页应满足: - 打开页面即可看到常用工作队列,不需要先打开高级查询; - 默认只暴露高频查询条件和必要字段,减少视觉噪声; - 状态页签、快捷筛选、精确筛选形成渐进式查询路径; - 业务人员使用业务语言,不需要理解 `AND`、`OR`、括号或查询表达式; - 重复查询可以保存、设为默认并再次使用; - 查询条件、分页、排序和当前视图可通过 URL 分享和恢复; - 查询权限、字段权限和数据范围始终由后端 SQL 强制执行; - 不保留旧查询接口、旧查询配置或旧数据结构的兼容转发层。 ## 2. 核心设计原则 ### 2.1 三层查询模型 ```text 工作队列页签 我现在要处理哪一类? ↓ 快捷筛选 我大概知道是哪几条? ↓ 更多筛选 我需要精确查找哪一条? ``` 对应到页面: 1. **工作队列页签**:预置常用状态或业务视图,进入页面即可使用。 2. **快捷筛选**:展示 3~5 个最高频的结构化条件。 3. **更多筛选**:按字段类型提供完整但易懂的筛选控件,默认收起。 暂不实现条件树、任意层级括号和查询语言。只有在后续确认存在稳定的分析师角色及真实使用需求后,才单独评估 L3/L4 能力。 ### 2.2 页签和筛选的职责分离 - 页签代表工作队列或预设查询视图,不等同于数据库状态字段; - 快捷筛选用于进一步缩小当前页签结果; - 页签条件与用户筛选条件之间固定使用 `AND`; - `有异常`、`我的订单`、`即将到期` 等跨字段场景也可以是页签; - 不把所有生命周期状态平铺到页签,默认显示 4~6 个,其余进入“更多”。 ### 2.3 业务语言优先 控件和文案不暴露技术表达式: - 多选枚举:显示“满足任一”或“满足全部”; - 日期:提供“今天、 本周、 本月、近三个月、自定义”; - 数值:提供“大于、小于、介于”; - 文本:默认“包含”,可选“等于、开头是”; - 布尔值:提供“是、否、不限”,不强迫用户选择一个值。 ## 3. 目标页面结构 ```text 模块标题 新增 导出 更多 全部 128 | 待处理 12 | 有异常 5 | 已订舱 31 | 已完成 72 | 更多 [ 搜索订单号、客户、提单号、船名、航次 ] [ 客户 ] [ ETD ] [ 业务员 ] [ 目的港 ] [ 更多筛选 ] 清除全部 客户:东方国际 × ETD:本月 × 订单号 | 客户 | 航线/目的港 | ETD | 负责人 | 状态 | 异常 | 操作 ``` ### 3.1 页面区域职责 | 区域 | 职责 | 默认行为 | | --- | --- | --- | | 页面头部 | 模块标题、主操作、导出和更多操作 | 保持简洁,不能被筛选器挤压 | | 工作队列页签 | 切换预设查询视图 | 默认打开模块配置的默认视图 | | 关键词搜索 | 跨关键字段模糊搜索 | 回车或防抖后查询,保留输入值 | | 快捷筛选 | 高频字段筛选 | 最多展示 3~5 个,可由模块配置 | | 更多筛选 | 完整字段筛选 | 抽屉或弹层打开,关闭后保留已选条件 | | 条件回显区 | 展示当前生效条件 | 每个条件可单独删除 | | 数据表格 | 展示精简后的默认列 | 默认 6~8 列,支持列设置 | ## 4. 工作队列页签设计 工作队列页签、关键词搜索和快捷筛选均必须通过模块查询配置生成,不能在页面组件中写死业务字段、状态值或显示顺序。前端只实现通用渲染器和交互,不针对海运订单、报关单等模块增加专用分支。 配置的职责边界如下: | 能力 | 配置决定的内容 | 前端通用能力 | | --- | --- | --- | | 工作队列页签 | 编码、文案、顺序、默认项、数量开关、预设条件、权限范围 | 渲染页签、切换视图、展示数量 | | 关键词搜索 | 占位文案、可搜索字段、匹配方式、触发方式 | 输入、清除、防抖/回车触发 | | 快捷筛选 | 字段、标签、顺序、控件类型、选项来源、默认值 | 根据字段元数据渲染控件、编辑值 | | 更多筛选 | 字段分组、可用操作符、字段顺序、显示条件 | 抽屉布局、字段控件和条件回显 | 模块配置变更后,页面无需重新发布前端代码即可改变查询入口。前端只允许从服务端返回的字段元数据生成查询请求,不接受页面代码中额外注入的可查询字段。 ### 4.1 页签配置模型 页签使用统一的预设视图模型,不限定只能绑定一个状态字段。 ```json { "moduleCode": "sea_order", "code": "pending", "label": "待处理", "type": "preset", "order": 10, "showCount": true, "isDefault": true, "query": { "conditions": [ { "field": "status", "operator": "in", "value": ["pending_audit", "pending_booking"] } ] } } ``` 一个模块的完整查询入口配置示例: ```json { "moduleCode": "sea_order", "defaultViewCode": "pending", "views": [ { "code": "all", "label": "全部", "type": "all", "order": 1, "showCount": true }, { "code": "pending", "label": "待处理", "type": "preset", "order": 2, "showCount": true, "isDefault": true, "query": { "conditions": [ { "field": "status", "operator": "in", "value": ["pending_audit", "pending_booking"] } ] } }, { "code": "exception", "label": "有异常", "type": "preset", "order": 3, "showCount": true, "query": { "conditions": [ { "field": "has_exception", "operator": "=", "value": true } ] } } ], "keywordSearch": { "placeholder": "搜索订单号、客户、提单号、船名、航次", "trigger": "enter_or_debounce", "fields": [ { "field": "order_no", "operator": "contains" }, { "field": "customer_name", "operator": "contains" }, { "field": "bill_of_lading_no", "operator": "contains" }, { "field": "vessel_name", "operator": "contains" }, { "field": "voyage_no", "operator": "contains" } ] }, "quickFilters": [ { "field": "customer_id", "label": "客户", "control": "select", "multiple": true, "optionSource": "customer", "matchMode": "any", "order": 1 }, { "field": "etd", "label": "ETD", "control": "date_range", "presets": ["today", "this_week", "this_month", "next_month"], "order": 2 }, { "field": "owner_id", "label": "业务员", "control": "select", "multiple": true, "optionSource": "current_user_scope", "matchMode": "any", "order": 3 } ], "filterGroups": [ { "code": "basic", "label": "基础信息", "order": 1, "fields": ["customer_id", "owner_id", "status", "carrier_id"] }, { "code": "schedule", "label": "船期与港口", "order": 2, "fields": ["etd", "eta", "pol", "pod"] } ] } ``` 配置中的 `field` 必须引用模块字段元数据中的合法字段,`control`、`operator` 和 `optionSource` 必须由后端字段定义校验。前端不得仅因为配置返回了一个字段就绕过字段权限。 支持的页签类型: - `all`:全部数据; - `preset`:模块配置的固定预设查询; - `personal`:用户保存的查询方案; - `shared`:角色或团队共享的查询方案。 ### 4.2 页签规则 - 默认展示 4~6 个页签; - 超出数量的视图进入“更多”; - 页签顺序、显示/隐藏、默认页签由模块配置和用户偏好共同决定; - 用户偏好只能调整布局和默认视图,不能扩大权限范围; - 页签统计数量使用与列表相同的权限、数据范围和过滤规则; - 统计请求失败不阻塞列表,显示无数量状态并记录错误日志; - 切换页签时保留用户已有的快捷筛选,若发生明显冲突则移除冲突条件并提示; - 页签条件和快捷/更多筛选条件始终按 `AND` 组合。 ### 4.3 数量统计策略 优先为待处理、有异常等具有行动价值的页签显示数量。数量统计接口应支持批量返回当前模块所有页签的数量,避免一个页签发起一次请求。 建议接口返回: ```json { "counts": { "all": 128, "pending": 12, "exception": 5, "completed": 72 }, "generatedAt": "2026-09-23T08:30:00+08:00" } ``` 数量不是强一致业务数据。允许短时间缓存,但必须在用户切换页签或刷新列表时提供可预测的刷新行为。 ## 5. 查询条件设计 ### 5.1 关键词搜索 每个模块配置一组关键词字段,关键词默认对这些字段执行跨字段模糊匹配。关键词框本身是通用组件,模块只提供占位文案、字段清单和触发策略。 示例: ```json { "keyword": { "placeholder": "搜索订单号、客户、提单号、船名、航次", "searchableFields": [ "orderNo", "customerName", "billOfLadingNo", "vesselName", "voyageNo" ] } } ``` 关键词搜索不要求用户先选择字段。字段可见性和可查询权限仍由后端校验。 ### 5.2 快捷筛选 每个模块配置 3~5 个快捷条件。选择依据:使用频率、业务价值、结果收敛效果和字段稳定性。页面不根据模块名称或路由写 `if/else` 决定快捷条件。 推荐字段: - 客户; - 负责人/业务员; - 日期范围; - 目的港或业务区域; - 运输方式、船公司等高频枚举。 快捷筛选控件由字段类型决定,不允许所有字段统一使用普通文本框。 ### 5.3 更多筛选 “更多筛选”以抽屉形式打开,按业务分组展示字段。默认只加载当前模块允许查询的字段,按需展开低频分组。 字段控件规则: | 字段类型 | 控件 | 默认语义 | | --- | --- | --- | | 枚举 | 多选下拉/标签选择 | 满足任一 | | 布尔 | 三态选择 | 不限 | | 日期 | 预置区间 + 自定义范围 | 区间包含起止日期 | | 数值 | 操作符 + 数值框 | 大于、小于、介于 | | 文本 | 匹配方式 + 输入框 | 包含 | | 多值字段 | 任一/全部切换 + 多选 | 满足任一 | 筛选抽屉底部固定提供: ```text [重置] [取消] [应用筛选] ``` 点击“取消”不改变当前已应用查询,点击“应用筛选”后统一刷新列表并回到第一页。 ## 6. 表格和视图设计 ### 6.1 默认列 每个模块必须定义一套精简的默认列,原则上控制在 6~8 列。默认列优先展示: - 用户识别记录所需的主标识; - 判断是否需要处理所需的状态; - 判断时效所需的日期; - 处理责任人; - 异常或风险提示; - 最常用的业务维度。 不在默认列表展示低频、技术性或详情级字段。低频字段通过详情页、列设置和导出字段获取。 ### 6.2 列设置和预设视图 提供以下视图能力: - 日常处理:面向操作员的精简列; - 运营跟踪:包含船期、港口、节点等字段; - 财务核对:包含金额、费用、开票等字段; - 自定义:用户调整后的列和顺序。 列可见性、列顺序和列宽属于用户布局偏好,不得影响后端权限判断。 ## 7. 保存查询方案 保存查询方案是本次重构的核心留存能力之一,优先级高于复杂逻辑组合。 支持: - 保存当前页签、关键词、筛选条件、排序和列视图; - 自定义名称; - 设为默认; - 最近使用; - 删除和重新命名; - 按用户、角色或团队共享; - 将高频方案固定为页签或快捷入口。 查询方案保存的内容应是结构化查询状态,不保存最终 SQL。 ```json { "name": "本月未订舱", "moduleCode": "sea_order", "viewCode": "pending", "keyword": "", "filters": { "etd": { "preset": "this_month" }, "bookingStatus": ["unbooked"] }, "sort": { "field": "etd", "direction": "asc" }, "columnPreset": "daily" } ``` ## 8. URL 状态和查询行为 > **实施状态(2026-09)**:URL 状态同步与查询分享**本期不做**(下期评估)。 > 原因:布局层的页签 key 与 keep-alive 缓存 key 都是 `route.fullPath`,直接把查询状态写进 > URL 会派生出新页签、破坏页面缓存;做 URL 同步需要先给列表路由做 key 归一化,属独立改动。 > 本节以下内容保留为下期目标。 以下状态必须可序列化到 URL: - 当前页签/查询方案; - 关键词; - 结构化筛选条件; - 排序; - 当前页码和每页数量; - 列视图(如需要)。 要求: - 刷新页面后可恢复查询; - 复制 URL 给有权限的同事后可打开相同查询; - 无权限字段或无效条件由后端拒绝并由前端清晰提示; - URL 不包含最终 SQL,不把权限判断交给前端; - 条件变化后重置到第一页;修改单个条件不清空其他条件。 ## 9. 后端和接口设计 ### 9.1 统一查询请求 前端提交结构化查询状态,后端负责将配置、页签条件、用户条件、权限和数据范围组合成 SQL。 ```json { "moduleCode": "sea_order", "viewCode": "pending", "keyword": "东方", "filters": { "customerId": [1001], "etd": { "from": "2026-09-01", "to": "2026-09-30" } }, "sort": { "field": "etd", "direction": "asc" }, "page": 1, "pageSize": 20 } ``` 后端处理顺序: 1. 加载模块、字段、页签和视图配置; 2. 校验字段可查询权限和操作符; 3. 合并页签预设条件和用户筛选条件; 4. 注入用户数据范围和权限条件; 5. 生成参数化 SQL 或执行模块配置中的合法 `SELECT`; 6. 返回分页数据、总数和必要的展示元数据。 ### 9.2 查询配置接口 页面首次加载时获取模块查询配置,配置接口应一次返回当前用户可用的视图、关键词搜索、快捷筛选、更多筛选分组、字段元数据和默认列。 ```json { "moduleCode": "sea_order", "version": 3, "defaultViewCode": "pending", "views": [], "keywordSearch": {}, "quickFilters": [], "filterGroups": [], "fields": [], "columnPresets": [] } ``` 配置接口必须完成以下处理: - 过滤当前用户无权查看的页签、字段和选项来源; - 过滤已停用或不存在的字段,记录配置错误; - 校验页签预设条件和快捷筛选字段的合法性; - 返回可直接渲染的字段类型、标签、操作符和选项元数据; - 返回配置版本,便于前端缓存失效和问题定位。 ### 9.3 建议接口 接口名称可按现有 API 风格落地,职责保持以下边界: ```text GET/POST 查询模块配置 POST 查询列表 POST 查询数量统计 GET 查询方案列表 POST 保存查询方案 PUT 修改查询方案 DELETE 删除查询方案 ``` 列表查询和数量统计必须复用相同的过滤、权限和数据范围构建逻辑,避免页签数量与列表结果不一致。 ### 9.4 数据库配置模型 新模型至少需要表达: - 模块可查询字段及字段类型; - 字段权限和可选操作符; - 关键词搜索字段; - 快捷筛选字段; - 更多筛选字段分组; - 默认表格列和列预设; - 工作队列页签; - 默认视图; - 查询方案的所属用户、角色或团队。 具体表名应复用现有模块、字段、权限和用户配置体系。若现有结构无法表达上述关系,直接调整为新结构,不增加旧结构兼容读取逻辑。 ## 10. 前端实现拆分 建议按页面职责拆分,具体目录以现有列表模块目录为准: ```text list-page/ ├── index.vue 页面编排、查询状态和数据加载 ├── WorkQueueTabs.vue 工作队列页签和数量 ├── KeywordSearch.vue 关键词搜索 ├── QuickFilters.vue 快捷筛选 ├── FilterDrawer.vue 更多筛选 ├── ActiveFilterPills.vue 已应用条件回显 ├── ResultTable.vue 表格和列设置入口 ├── SavedQueryMenu.vue 保存查询方案和最近使用 └── query-utils.js 查询状态序列化、规范化和纯转换函数 ``` 职责要求: - `index.vue` 持有唯一查询状态源,负责加载配置、拼接请求、分页和刷新; - `index.vue` 不包含模块编码判断、业务状态常量、固定快捷字段或固定关键词字段; - 各筛选组件只负责展示和编辑条件,通过 `v-model` 或语义明确的事件通信; - `WorkQueueTabs.vue`、`KeywordSearch.vue` 和 `QuickFilters.vue` 均只消费配置,不内置模块专用选项; - 不在多个组件复制查询条件; - 不在子组件中自行请求同一列表或配置数据; - 查询状态规范化、URL 编解码和条件标签生成等纯逻辑集中维护并可单测; - 组件不直接拼接 SQL,也不承担权限判断。 ## 11. 实施阶段 ### 阶段一:查询模型和接口 - 确认新查询请求、响应和配置结构; - 建立字段类型、操作符和筛选值的统一定义; - 建立页签/预设视图模型; - 建立模块查询配置接口,统一返回工作队列、关键词搜索、快捷筛选和字段元数据; - 为首批模块录入查询配置,不在前端页面写入模块专用查询定义; - 建立统一列表查询和数量统计服务; - 将权限、字段权限和数据范围接入查询构建流程; - 直接切换到新接口,不保留旧查询兼容入口。 ### 阶段二:列表页基础体验 - 实现工作队列页签; - 实现批量数量统计; - 实现关键词搜索; - 实现快捷筛选; - 实现条件回显、单条件删除和全部清除; - 实现查询变更后的分页重置; - 精简默认表格列。 ### 阶段三:更多筛选 - 实现字段类型到控件的映射; - 实现日期预设区间和自定义范围; - 实现数值比较和文本匹配方式; - 实现多值字段“任一/全部”; - 实现筛选抽屉的应用、取消和重置行为; - 实现空结果提示和条件放宽入口。 ### 阶段四:保存和个性化 - 实现保存查询方案; - 实现默认视图、最近使用和方案删除; - 实现列预设和用户列布局; - 实现方案共享; - 实现 URL 状态同步和查询分享。 ### 阶段五:按模块推广 - 选择海运订单、报关单、费用单等状态清晰且使用频繁的模块作为首批模块; - 为每个模块定义 4~6 个工作队列页签; - 根据实际查询日志调整快捷字段和默认列; - 再推广到客户档案等没有明显生命周期的模块,此类模块可以只启用关键词、快捷筛选和更多筛选,不强制配置页签。 ## 12. 测试计划 ### 12.1 后端测试 - 页签条件与用户筛选条件按 `AND` 合并; - 多选字段“任一/全部”生成正确 SQL; - 日期边界、时区和包含起止日期行为正确; - 数值比较符行为正确; - 关键词跨字段搜索行为正确; - 字段权限、模块权限和数据范围始终生效; - 列表数量与页签统计使用相同条件; - 非法字段、非法操作符和越权条件被拒绝; - 分页、排序和筛选参数不会产生非查询 SQL; - 查询方案只能被授权用户读取或修改。 ### 12.2 前端测试 - 默认页签和默认条件正确加载; - 切换页签保留或清理筛选条件的规则正确; - 条件标签可单独删除; - 更多筛选的取消不影响已应用条件; - 应用筛选后回到第一页; - 刷新或打开分享 URL 可恢复查询; - 空结果状态能够定位和清除条件; - 数量加载失败不阻塞列表; - 表格列视图切换不改变查询结果; - 保存、修改、删除和设为默认查询方案正常。 ### 12.3 验收场景 至少用真实业务流程验证: 1. 业务员进入海运订单,直接点击“待处理”处理自己的工作队列; 2. 在“待处理”下筛选某客户和本月 ETD; 3. 通过“更多筛选”查找同时包含多个服务项的订单; 4. 将“本月未订舱”保存为个人默认查询; 5. 复制查询 URL 给另一位有权限的同事; 6. 无权限用户打开同一 URL 时看不到越权数据; 7. 查询无结果时能明确看到条件并一键放宽或清除。 ## 13. 观测指标 上线后按模块记录以下指标,用于持续收敛默认配置: - 从进入列表到首次有效查询的耗时; - 页签点击占比及各页签使用频率; - 快捷筛选使用频率; - 更多筛选打开率和应用成功率; - 空结果率; - 查询后再次修改条件的次数; - 保存查询方案数量和复用次数; - 默认列设置被修改的比例; - 列表查询接口耗时、数量统计接口耗时和错误率。 判断标准不是“可配置项是否足够多”,而是业务是否更少打开复杂筛选、更少遇到空结果、更快找到需要处理的数据。 ## 14. 明确不做的事项 - 不在第一版实现任意层级的 AND/OR 条件树; - 不实现查询表达式语言; - 不把所有字段默认展示为筛选项; - 不把所有生命周期状态都平铺为页签; - 不把最终 SQL 保存到用户查询方案; - 不在前端执行权限过滤代替后端 SQL; - 不保留旧查询接口、旧查询配置、旧字段映射或旧数据兼容逻辑; - 不为每个业务模块复制一套专用查询接口; - **本期不做**:URL 状态同步与查询分享(见 §8 实施状态);保存查询方案与列预设视图亦下期再做。 ## 15. 完成标准 - 新查询模型和新接口在目标模块生效,旧查询入口已移除; - 工作队列页签、关键词搜索和快捷筛选均由模块配置生成,前端没有模块专用分支; - 新增或调整模块查询入口只需要修改模块配置和字段元数据,不需要修改前端组件代码; - 列表页默认只展示必要的工作队列、筛选条件和表格列; - 业务人员可以不打开“更多筛选”完成主要日常工作; - 复杂查询通过字段类型匹配的业务控件完成,不需要理解技术表达式; - 查询条件可回显、单独修改、清除和通过 URL 恢复; - 常用查询可以保存、设为默认并再次使用; - 页签数量与列表结果遵守相同的权限和数据范围; - 关键前后端测试通过,真实业务验收场景可完成; - 查询日志和性能指标已接入,能够根据使用数据继续调整页签、快捷字段和默认列。