ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI 软件开发实战教程(十):把微信群消息变成结构化发布

AI 软件开发实战教程(十):把微信群消息变成结构化发布 “AI 软件开发实战教程”系列第 10 篇把“八点左右”“现在出发”等群聊表达转换成可计算的时间契约并用 TDD 完成发布、查找、详情和安全群文案。邻行最初面对的是这样的消息【车找人】 【时间】明早 8:05 【路线】万科环普/中软/阿里/华为它对熟悉小区的人很好理解对系统却不够明确“明早”是哪一个日期8:05 是必须准时还是前后都可以发布者准备等到什么时候斜杠分隔的是多个终点还是大范围方向消息被重复发送时是新需求还是同一次点击。K2 的任务不是给微信群加一个更漂亮的输入框而是把这些含义变成可以保存、筛选和验收的产品事实。时间不是一个字段每条出行信息至少需要四个时间事实预计出发时刻 可出发窗口开始 可出发窗口结束 停止产生新候选的截止时刻只填写预计时间时邻行默认预计 08:20 可出发 08:05–08:35 匹配截止 08:05这里“匹配截止”不是最晚出发时间。它表示系统从该时刻起不再形成新候选让用户还有机会改乘其他交通方式。上一篇产品审阅中曾出现一个矛盾表达“可出发到 08:35最晚等到 08:20”。正式规则把含糊的“最晚等到”拆成两个概念后页面也不再使用那句话。先用纯函数固定所有边界时间规则不应该先藏进表单或数据库模型。K2 先写一个没有数据库副作用的build_schedule输入当前时刻和用户选择输出完整时间契约。测试固定当前时间为北京时间 08:00覆盖预计 09:00得到 08:45–09:15截止 08:45预计 08:10距离不足 15 分钟截止等于 08:10并标记时间紧迫选择现在出发窗口为 08:00–08:15截止 08:15把现在出发窗口延长到 08:30未手改截止时一起延长用户单独提前截止时不再自动覆盖预计时刻在过去、窗口不包含预计时刻、截止已到或晚于窗口结束时拒绝。第一批测试因为apps.trips尚不存在而失败随后才创建规则模块。这种做法让时间错误可以精确定位。否则一个浏览器测试只会说“发布失败”很难判断是时区、表单、数据库还是页面脚本造成。“现在”不能保存成一个会变化的词用户点击“现在出发”时数据库不会保存字符串now。服务在提交瞬间读取一次服务器时间保存确定的带时区时间戳window_start 提交时刻 expected_at 提交时刻 window_end 提交时刻 15 分钟 matching_deadline 提交时刻 15 分钟以后打开详情看到的是当时保存的具体时刻而不是每次刷新都向后移动的“现在”。数据库统一保存 UTC日期和页面显示按Asia/Shanghai解释。测试也使用带时区的固定时刻避免依赖运行机器的本地时区。车找人和人找车不是同一张随意表单两种信息共享日期、时间和路线却有一个关键差异车找人必须填写正整数座位人找车不能提交座位。这个规则同时存在于三层表单给出可修复错误发布服务拒绝绕过表单的非法调用数据库 CheckConstraint 保证车主座位大于零、乘客座位为空。只在页面隐藏座位框是不够的。旧页面、手工请求或后续代码都可能继续提交值服务和数据库仍要守住同一个事实。地点必须来自社区词表首版不采集自由文本说明、联系方式或精确住宅地址。管理员维护大范围地点例如万科悦城软件新城国际医学中心。地点显式属于社区停用后不能用于新发布。表单使用封闭选择控件服务再次检查起终点都属于当前用户社区、仍然启用并且不能相同。地点别名模型也已经建立管理员可以把“中软”“软件新城”等输入习惯整理到标准地点。当前社区地点很少页面先使用原生封闭选择大量地点时的搜索体验留到完整 UI 验收增强但不能为了搜索方便改回任意文本。重复点击不能创建两条信息移动网络中用户可能双击按钮、返回重试浏览器也可能在超时后重新提交。发布页每次展示时生成一个随机幂等键提交时和用户一起形成数据库唯一约束unique(publisher, idempotency_key)第一次请求创建稳定 UUID 信息后续相同请求返回原信息。服务测试连续执行两次相同命令证明数据库最终只有一条记录。幂等键不是短编号。短编号是每条信息独立生成的四位随机辅助标识用于群里讨论“哪一条信息”不能稳定追踪同一个发布者。大厅查询本身就是状态规则默认大厅只显示同一社区 状态有效 当前时间早于匹配截止 当前时间早于预计出发后台过期任务即使晚运行查询也不会把已经截止或已经出发的信息继续当成可联系内容。成员可以按日期、类型、起点、终点和本地时间范围筛选。首版没有“方向”控件也没有关键字搜索。路线兼容关系属于后续候选规则不应该变成另一个含糊筛选入口。详情链接使用随机 UUID并在查询时同时限制社区。知道另一个社区的 URL 也只会得到 404链接本身不绕过登录和社区资格。群文案是主动分享的结构化快照发布成功后页面生成可以预览和手动复制的群文案【车找人】 【日期】2026-08-03 【时间】08:05–08:35 【路线】万科悦城 → 软件新城 【座位】2 个 【状态】正在寻找 【编号】A7K2 【详情】https://example.com/trips/...文案只包含用户已经主动选择公开的大范围信息。它不包含登录账号、微信号、喵码、精确地址或自由说明。详情页 Open Graph 描述也遵守同样边界。自动测试同时扫描 HTML、群文案和浏览器页面而不是只检查数据库字段。浏览器连续发现三个真实问题HTTP 测试通过后Playwright 在 375×812 视口执行登录 → 打开发布页 → 选择车找人 → 填写日期、时间、地点和座位 → 发布进入详情 → 检查群文案无敏感资料 → 返回大厅看到刚发布的信息第一次失败发生在发布类型。代码定义的是普通 ChoiceField模板却把它当单选卡片迭代浏览器实际得到没有正确标签的下拉选项提交提示类型必填。将字段明确改为 RadioSelect 后修复。第二次失败发生在路线标题。视觉箭头→被标成读屏忽略辅助技术只读出两个地点没有表达方向。页面增加视觉隐藏的“到”可访问名称变成“万科悦城 到 软件新城”。第三次失败更接近业务默认大厅一直为空。无查询参数时筛选表单处于未绑定状态旧代码只在form.is_valid()为真时执行查询。修正后先执行默认开放信息查询只有用户实际提交且筛选有效时才覆盖。这些问题都不是增加更多单元测试能自然发现的。真实浏览器把表单语义、无障碍树和完整页面数据流连在一起。如何更新验收状态K2 完成后自动通过的场景包括车主和乘客结构化发布默认窗口、截止、紧迫边界和过去时间拒绝重复发布幂等五类大厅筛选且没有方向控件现在出发及窗口联动发布表单和群文案没有自由文本与联系方式。仍然不能提前关闭AC-12 的查询部分已通过但 K6 还要把状态正式落为过期AC-41 已证明交换前只显示角色和随机短编号交换后的微信号权限等待 K4真实提醒、WebKit 和微信真机仍未验证。任务完成不等于所有相邻能力都已经完成。本节点结果K2 收口时65 个非浏览器测试通过分支覆盖率 90.24%Ruff、格式、mypy strict、迁移和 Django 检查通过V0、K1、K2 共三条 Chromium 用户旅程通过发布详情和群文案不包含测试登录账号、微信号或喵码WebKit、PostgreSQL 实跑和微信真机限制继续如实保留结果只形成本地提交不推送。写在最后把群消息结构化不是把一段文字拆成几个输入框。真正的工作是消除会影响匹配和提醒的歧义同时不采集产品根本不需要的个人信息。日期、时间窗口、截止、地点、座位和状态都必须有单一含义并能被数据库、查询和页面共同验证。下一篇进入 K3当一条车找人和一条人找车先后出现时系统怎样用明确规则形成“可能同路”的候选保存可解释原因并为双方创建同一个业务事件下的两条站内提醒。关键代码与操作下面的简化测试固定同一个幂等键连续发布两次核心断言是数据库最终只有一条信息deftest_repeated_publish_returns_one_trip(user,command):firstpublish_trip(useruser,commandcommand,nowNOW)secondpublish_trip(useruser,commandcommand,nowNOW)assertsecond.pkfirst.pkassertTripPost.objects.count()1验证命令make bugfix TESTtests/trips/test_publishing.py::test_repeated_publish_command_returns_one_trip这类测试比只禁用提交按钮更可靠因为重试请求和旧客户端仍会经过服务与数据库。本篇验证摘要日期、预计时刻、可出发窗口和匹配截止被保存为含义明确的时间事实车主座位、社区地点和起终点规则同时由表单、服务与数据库约束保护发布使用幂等键重复提交只返回同一条信息大厅和详情从查询层限制社区与有效状态不能靠隐藏模板代替权限移动浏览器已经走通发布、详情、群文案和大厅回看文案不包含账号或联系方式。附录相关工具与仓库gstack仓库garrytan/gstack地址https://github.com/garrytan/gstackdev-harness仓库Dev-Wiki/dev-harness地址https://github.com/Dev-Wiki/dev-harnessUI UX Pro Max Skill仓库nextlevelbuilder/ui-ux-pro-max-skill地址https://github.com/nextlevelbuilder/ui-ux-pro-max-skill
返回列表