项目复盘 · 2018
横向产品工程:让搜索、阅读和研究工作台逐渐成为一体
一轮跨产品的前端、服务端、交互设计与运维建设,把搜索筛选、账号、上传、笔记、编辑器和财务分析逐步连接成统一研究体验。
当一个团队同时维护搜索、产业链、财务报表和研究工具时,最容易出现的浪费不是重复写一个按钮,而是每个产品都拥有不同的账号、筛选、阅读、笔记和上传逻辑。用户在不同页面之间切换时,需要重新理解交互,研发也要重复修复相似问题。
FRONTEND、SER、UIUE 和 DEVOPS 四个项目记录了一轮横向整合。它没有单独的商业名称,却把多个上层产品需要的共同能力逐渐沉淀为研究工作台。
搜索交互从“能用”走向一致
FRONTEND 项目首先集中处理搜索页。工作从意见收集和交互框图开始,随后细化搜索框、股票代码、语义距离、搜索位置、时间范围、六类过滤器、保存搜索和个人中心。
Confluence 中的过滤器定义把查询拆成时间、标签、来源与文本条件:时间包含 7 天、30 天、90 天、半年、一年、一年半、两年、全部和自定义范围;文本条件还考虑是否做关键词扩展与重复点击。Jira 的实现事项则继续约束交互状态,例如股票代码按输入顺序追加、语义距离出现非默认值时整体变色、自定义时间起点选完后焦点自动进入终点。这些不是纯视觉规定,而是在给一套查询 DSL 建立可见的编辑器。
许多事项看似只是像素和颜色调整,实际上影响用户是否理解查询状态。例如,多选过滤器取消一项后仍显示全选,会让用户误判检索范围;自定义时间未选择日期时若不回到“不限”,会制造不可见条件;下拉菜单延迟和阅读区截断则直接增加操作成本。
由此可以恢复出一条重要的不变量:控件显示状态、保存的搜索条件和实际发给后端的参数必须三者一致。保存搜索失败、小屏适配和筛选弹层闪现分别位于账号状态、响应式布局和浏览器渲染层,但最终都会破坏同一个用户承诺——“我看到的条件就是系统执行的条件”。最有效的回归测试不是逐像素截图,而是为一组筛选操作同时断言 URL 或请求体、控件状态、结果摘要和重新载入后的恢复值。
没有发现可与四组工单一一对应的统一源码,所以下面是从交互说明恢复的等价伪代码,不是原前端实现。它把“显示状态、请求参数、保存结果”三者一致变成可测试规则:
function applyFilter(state: SearchState, action: FilterAction) {
const next = reduceVisibleControls(state, action)
const request = serializeQuery(next.filters, next.sortMode)
const summary = describeQuery(request)
assert(summary.timeRange === next.controls.timeRangeLabel)
assert(summary.selectedTags.length === next.controls.selectedTags.length)
if (action.type === "CLEAR_CUSTOM_TIME") {
assert(request.startDate === undefined)
assert(request.endDate === undefined)
}
return {
...next,
request,
summary,
savedSearch: versionQuery(request, next.expansionPolicy),
}
}团队还尝试统一按钮圆角、悬停和点击状态、筛选器展开方式与不同产品的搜索框样式。这些工作表明设计开始从单页标注转向组件规则,不过历史事项仍频繁要求“按标注还原”,说明当时尚未建立完整的设计令牌与自动化视觉校验。
服务端把研究动作串成工作流
SER 项目覆盖账号、上传管理、工作台、笔记与素材、编辑器和提醒,也承担财务报表与模型分析的多项修正。这些能力共同组成一条研究流程:用户先登录并保存搜索,再上传或阅读资料,把片段转为笔记,最后在编辑器中整理输出。
这条链路比孤立功能更重要。上传文件若没有所有者与权限,笔记就无法安全引用;搜索条件若不能保存,提醒就不知道监测什么;编辑器若不能保留来源,研究成果又失去可追溯性。横向服务需要围绕对象关系设计,而不是把若干接口简单放在同一个项目里。
产品文档给出了更具体的对象关系。上传入口支持多文件,文档可以关联公司和标签,关联公司应进入股票代码过滤范围;上传内容仅本人可见,并在本人的搜索结果中优先。笔记 V2 则从阅读器中的高亮文本启动,悬浮工具栏同时提供“生成笔记、搜索当前文档、搜索全部文档”,保存后用可收起的提示反馈。于是一个笔记至少需要保存用户、源文档、选区或截图、创建时间和可见性;若只存最终文本,之后就无法回到原文验证。
这也暴露了搜索排序中的多目标冲突:个人上传内容需要优先,但普通关键词结果又应按相关性;无关键词、仅股票代码时,产品建议按时间排序。合理实现应先明确查询场景,再应用排序策略,而不是把“个人内容加权、文本相关性、时间新鲜度”混成一个无法解释的总分。每个命中还应携带排序原因,才能帮助研究者判断结果为何出现。
财务报表相关事项还包括固定表头、按类型展示、现金流格式、切换主体后刷新模型,以及把模型大图保存到笔记。它们说明工作台不仅处理文字,也开始承载表格和分析图形。
“切换主体后模型没有刷新”和“笔记应保存大图”分别揭示了状态与快照语义。模型图必须把公司主体、报表期、模型类型和计算版本纳入缓存键,任何一项变化都要失效;保存到笔记的则应是带这些元数据的可复现快照,而不是只保存当前画布像素。否则研究者后来打开笔记时,既不知道图对应哪家公司,也无法解释数据更新前后的差异。
设计项目定义共同语言
UIUE 项目完成网站、工作台和财务报表界面设计,并持续收集测试细节。它与 FRONTEND 的关系类似设计规范与实现验收:前者定义页面结构和视觉目标,后者把目标拆成可执行问题。
历史记录中还出现浏览器差异。同一个提示文字在不同浏览器中位置不同,筛选弹层也有闪现问题。仅靠静态稿无法发现这些行为,设计验收需要包含真实数据、不同视口、键盘操作和目标浏览器测试。
运维事项揭示共同底座
DEVOPS 项目只有三条事项,但分别涉及协作系统独立部署、境外公司数据接口和专利搜索集群。它更像早期横向支持队列,而不是成熟的平台工程项目。
专利数据迁移到更快存储并修正日期格式,说明性能问题有时来自数据建模和存储介质,而非前端;协作系统独立部署则体现团队开始隔离项目基础设施。三项均被标记完成,但现存记录缺少持续监控、备份演练与服务级别指标,无法确认后续运行质量。
统一体验仍有尚未完成的边界
四个项目的大部分事项已经完成,剩余工作集中在三个方向:产业链的更多图谱漫游动作、移动应用内部数据采集,以及特定浏览器的筛选弹层问题。FRONTEND 中的深度学习表格抽取也仍为待办,而且它本质上属于文档处理能力,并非普通前端功能。
这些遗留项提醒我们,横向项目应保持清晰边界。设计系统、研究工作流和数据抽取需要不同验收方法;全部放进“前端和服务端”队列,会让完成比例掩盖真正的技术风险。
项目留下的经验
- 跨产品能力应围绕统一对象模型建设:用户、搜索、文档、笔记、素材、提醒和文章之间需要稳定关系。
- 筛选状态必须始终可见且可清除,控件视觉状态要与真实查询参数一致。
- 保存搜索要同时版本化查询条件、排序场景和关键词扩展策略,重新载入后才能复现同一检索。
- 设计规范应沉淀为组件和令牌,并用多视口、多浏览器和真实数据做验收。
- 上传、笔记和编辑器要保留来源、所有权和权限,才能支持可追溯的研究流程。
- 分析图进入笔记时应保存主体、数据期、模型版本与生成参数;图片只是展示副本,不是完整证据。
- 横向工程队列应区分产品组件、数据算法和基础设施,分别制定完成标准。
- 运维任务完成后还需要监控、备份和恢复证据,不能以“部署成功”替代长期可靠性。
证据边界
本文覆盖四个 Jira 项目,共 54 条事项:FRONTEND 有 28 条,其中 27 条完成、1 条待办;SER 有 19 条,其中 16 条完成、3 条待办;UIUE 有 4 条,其中 3 条完成、1 条待办;DEVOPS 的 3 条事项均完成。
Confluence 的产品、Feature、交互与前端空间保存了搜索、上传、笔记、工作台和组件说明。GitLab 中也存在多个 Vue、JavaScript、Java 和 PHP 项目,但当前快照没有一套仓库能够与这四个 Jira 项目完整对应,且部分仓库属于后续产品。本文据此确认共同功能经过设计与实施,不推定它们已经形成单一代码库、完整设计系统或长期统一的平台。