13 KiB
13 KiB
开发提示词:批量导出"购物车"(清单式收集 → 一键打包下载,离线版+在线版两端一致)
用途:把本文件交给 AI 会话执行。完成后按"验收标准"逐条核对,结果回写 OnebotCatalog\项目总览.md(进展记录 + 踩坑表 + 最后更新行)。 背景必读:OnebotCatalog\项目总览.md、OnebotCatalog\src\App\MainWindow.cs(桌面 4 标签页 + 参数面板下载区 + 参数表)、OnebotCatalog\web\app.js / index.html / style.css(网页 4 标签页)、OnebotCatalog\开发提示词-窗口内3D-WebView2方案B.md(提示词文体参照)。
一、角色与任务
你是资深 WPF/前端工程师,在既有项目 OnebotCatalog(C# / .NET Framework 4.8 代码式 WPF + 纯静态网页版)上实现淘宝式购物车批量导出:用户浏览选型过程中把多个型号"加入清单"(跨系列、跨型号,选型流程完全不受干扰),随时打开清单一键打包下载(zip 含全部 STEP + BOM 清单)。两端功能、交互、文案完全一致(项目已定规矩)。
二、需求定稿(语义先行,避免歧义)
- 购物车 = 跨系列清单:可加入不同系列的不同型号;同一型号重复加入 → 提示"已在清单中"(不清空、不加量、不跳转)。
- 不影响选型(淘宝式,用户 2026-08-24 明确):加入清单是"旁路操作"——加入后当前选型状态、3D 视图、参数面板完全不变、不跳转、不清空。
- 购物车生命周期:网页 = 浏览器会话内(刷新浏览器才清空);桌面 = 软件运行期间(重启软件才清空)。
- 切换系列 / 切换型号 / 切标签页 / 搜索跳转 / 平替跳转 / 参数表任何操作,一律不触碰购物车——购物车状态对象与选型状态彻底解耦(两端 cart 独立于 sel/series 状态)。
- 三处入口(两端一致):
- 参数面板下载区新增【加入清单】按钮(与【下载 STEP】【下载 PDF】并排,选型完成才显示)
- 参数表每行行尾"+"小按钮(一键加该行,不触发行双击/筛选)
- 顶部栏常驻【清单 (N)】按钮,N=件数实时角标,点击打开清单面板
- 清单面板:
- 桌面:独立非模态 Window(Owner=主窗口),DataGrid 列表;网页:右侧滑出抽屉(遮罩点击关闭,不误触面板外按钮)
- 列:型号 | 系列 | 规格摘要 | 文件名 | 数量(可编辑≥1,默认1) | 操作(删除)
- 底部按钮:【清空】【下载全部 (zip + BOM)】;面板标题与角标实时同步件数
- 数量语义定死:zip 中每型号只打包一份 STEP,数量只体现在 BOM.csv 的"数量"列(不做重复文件、不改文件名)
- 一键打包(两端产物结构完全一致):
ONEBOT_清单_<时间戳>.zip:内含各型号 STEP(文件名=型号编码,保留原后缀)+BOM.csv+清单.txt(人类可读版 BOM)BOM.csv列:序号, 型号编码, 系列代码, 系列名, 数量, 参数摘要(键=值 分号分隔), STEP文件名;UTF-8 带 BOM(Excel 中文不乱码);字段含逗号/引号按 CSV 规范转义
- 打包引擎:
- 桌面:System.IO.Compression.ZipArchive(net48 内置,零新依赖)
- 网页:JSZip(MIT 开源,~100KB 单文件,放
web\libs\jszip.min.js,需用户批准下载,交付说明注明版本/来源/许可)——纯静态无后端,前端逐项 fetch 同源 STEP 二进制 → 内存打包 →URL.createObjectURL触发下载
- 整合旧功能:桌面参数表多选 +【批量导出所选】改造为【加入清单】(勾选行批量加入,提示"已加入 N 项"),删除旧直接导出逻辑,统一走清单(避免两套批量路径);网页参数表本就无批量导出,直接加"+"。
三、两端统一文案表(开发时直接抄,保证一致)
| 场景 | 中文 | 英文 |
|---|---|---|
| 加入按钮 | 加入清单 | Add to Cart |
| 顶栏角标 | 清单 (N) | Cart (N) |
| 重复加入提示 | 该型号已在清单中 | Already in cart |
| 加入成功 | 已加入清单 (共 N 项) | Added to cart (N items) |
| 批量加入 | 已加入清单 N 项 | N items added to cart |
| 面板标题 | 我的清单 | My Cart |
| 数量列 | 数量 | Qty |
| 删除 | 删除 | Remove |
| 清空 | 清空 | Clear All |
| 下载全部 | 下载全部 (zip + BOM) | Download All (zip + BOM) |
| 打包中 | 打包中... | Packing... |
| 空清单 | 清单为空, 请先加入型号 | Cart is empty |
| 部分失败 | 打包完成, 但以下型号文件缺失: xxx | Packed, but missing: xxx |
四、现状速览(改动前先读)
- 桌面
src\App\MainWindow.cs:TryUpdateSelection()(已选型号后_btnDownload/_btnDownloadPdf显隐、_curModelCode平替过滤);参数面板 actions 区(2026-08-24 加的_btnDownload/_btnDownloadPdfStackPanel);BuildGridTab(_grid多选 +ExportSelected()+ 右键列头筛选 + 双击NavigateToModel);顶栏 StackPaneltop;4 标签页索引:0=3D/尺寸图, 1=参数表, 2=搜索, 3=平替对照 - 桌面 STEP 读取:
_pkg.ReadAsset(v.step)/OpcPackage.ExtractStepTo(v, path);Variant 有@params字典、modelCode、step - 网页
web\app.js:selectSeries(重置 sel/ranges/tableFilter——不得动 cart)、updateSelection(下载按钮显隐 +v.step相对路径如step/UCBM32.stp)、renderTable(行点击带入选型 + 2026-08-24 列筛选,行尾加"+"注意 stopPropagation) - 网页 STEP 位置:站点根
step\目录(发布时从 .opc 解包),fetch 相对路径即可 - 版本号规范:网页 index.html 引
app.js?v=N、style.css?v=M,每次发布 +1;桌面改 .cs 后必跑sample-data\tools\fix-bom.ps1
五、硬性约束(违反即返工)
- 完全离线可用(两端);桌面编译环境无 .NET SDK(csc +
lib\DLL/reference,新库须放 lib\) - 两端交互/文案/输出格式一致(见文案表);桌面中英双语
_lang.T(zh,en),网页t(zh,en) - 不影响选型主流程(需求第 2 条——验收重点)
- 不改数据管线、.opc 格式、发布六步结构
- JSZip 必须经用户批准下载并在交付说明注明版本/来源/许可(MIT)
- 编辑含中文 .cs/.ps1 后必须 fix-bom;网页文件 UTF-8 无 BOM 即可
- 客户版与开发版同一代码(
#if CUSTOMER_BUILD只控制维护入口);清单功能两版都有
六、实施步骤
桌面(src\App)
- 新文件
Cart.cs(命名空间 Ounibo.Catalog.App):class CartItem { string ModelCode; string SeriesCode; string SeriesName; string StepPath; string ParamsSummary; int Qty = 1; } - 状态:
List<CartItem> _cart;int CartCount => _cart.Sum(x => x.Qty)(角标显示件数=数量总和还是行数?——定死:角标显示行数,BOM 数量列体现 Qty,简单不混淆) - 加入清单:
AddToCart(Variant v, Series s)——重复判断(ModelCode 忽略大小写)→ 提示已存在;成功仅更新角标 + 状态栏,严禁写_sel - 三处入口:参数面板 actions 区【加入清单】(
TryUpdateSelection里随_btnDownload同显隐,点击用当前已解析的 variant);参数表"+"列(DataGridTemplateColumn内 Button,Click里e.Handled防止干扰行选择/双击/右键筛选);顶栏【清单 (N)】 - 清单窗口
CartWindow:非模态 Window(Owner 主窗口),DataGrid 列:型号/系列/规格/数量(可编辑绑定 Qty)/删除(按钮列);底部【清空】【下载全部 (zip + BOM)】;窗口关闭不丢数据(_cart 在主窗口) - 打包:SaveFileDialog(默认名
ONEBOT_清单_yyyyMMddHHmmss.zip)→ ZipArchive:遍历_pkg.ReadAsset(item.StepPath)写ModelCode+原扩展名;BOM.csv 与 清单.txt 用 UTF8Encoding(true);打包完成后 MessageBox 提示路径 - 整合:
ExportSelected改为"选中行批量 AddToCart + 提示已加入 N 项";_btnExport文案改【加入清单】 - 文案走文案表 + 状态栏反馈
网页(web\)
- 引入 JSZip:下载官方最新稳定版 jszip.min.js →
web\libs\jszip.min.js;index.html<script src="libs/jszip.min.js?v=1"></script>;交付说明注明版本/来源/许可 - 状态:
state.cart = [](结构同 CartItem,StepPath=相对路径)——selectSeries/refreshOptions/renderTable/jumpToModel 全部不得触碰 - 三处入口:
updateSelection()里下载区显【加入清单】;renderTable每行尾"+"(onclick内ev.stopPropagation()防触发行点击);header 加【清单 (N)】角标按钮 - 清单抽屉:右侧 fixed 面板 + 半透明遮罩;行含数量
<input type=number min=1>、删除按钮;底部【清空】【下载全部 (zip + BOM)】;遮罩点击只关面板(面板内点击stopPropagation) - 打包:
new JSZip()→ 逐项await fetch(item.step)(失败收集到 missing 列表继续)→zip.file(name, blob)→zip.file('BOM.csv', '' + csv)、zip.file('清单.txt', txt)→generateAsync({type:'blob'})→ createObjectURL + a[download] 触发;打包中按钮文案"打包中..."并禁用防连点;missing 非空时提示"打包完成, 但以下型号文件缺失: xxx" - 文案走文案表;不调用 selectSeries/refreshOptions
发布与回归
- 桌面:fix-bom → build.ps1(双版)→ 冒烟 →
--selftest31 项不变 - 网页:index.html 版本号 +1 → 停 serve-web → publish.ps1 → 重启 serve-web
- 交付说明:JSZip 来源/版本/许可 + 两端截图对照
七、验收标准(逐条核对)
- 两端:选型号 A → 加入清单 → 选型界面无任何变化(参数不清空、3D 不跳)→ 换系列选型号 B → 加入 → 角标 (2);再切回系列 A、切所有标签页、搜索/平替跳转、参数表双击/列筛选,清单仍 (2) 内容不变(网页仅刷新、桌面仅重启才清空)
- 重复加入同型号 → 提示"已在清单中",件数不变
- 参数表"+"与勾选批量加入正常,且不干扰行双击带入选型、右键列筛选、范围筛选
- 清单面板:数量改 3 → 删除一项 → 清空 → 角标实时同步
- 下载全部 → zip 含全部 STEP + BOM.csv + 清单.txt;Excel 打开中文无乱码、列齐全;数量 3 的型号 zip 中仍只有一份文件、BOM 数量列=3;两端产物结构一致
- 网页打包中防连点;断网桌面全流程可用;STEP 缺失时跳过并明确提示缺失型号(不整体失败)
- 自测 31 项不变;客户版发布目录运行正常
- 两端文案完全一致(对照文案表,中英切换正确)
八、已知陷阱(本项目血泪 + 本功能专属)
| # | 陷阱 | 对策 |
|---|---|---|
| 1 | 中文文件/CSV 乱码 | BOM.csv 必须 UTF-8 BOM(桌面 UTF8Encoding(true) / 网页 '' 前缀);.cs/.ps1 改完 fix-bom |
| 2 | GUI exe 用 & 启动不等待,$LASTEXITCODE 空 |
Start-Process -Wait -PassThru,核对 log 时间戳 |
| 3 | 发布目录被运行中程序锁 | 发布前停 serve-web 与运行中 exe(红线) |
| 4 | zip 内重名冲突(跨系列存在同名型号) | 打包前校验,冲突加后缀 _系列码,BOM 列同步注明 |
| 5 | 网页逐项 fetch 大 STEP 内存峰值 | 逐项 fetch 后立即 zip.file(JSZip 持有 blob,不必先全存数组);避免一次性 concat |
| 6 | 空串枚举参数摘要显示 | 摘要统一走 displayValue/显示名映射,空值显示"(无)" |
| 7 | 加入清单误写 _sel/state.sel 导致选型被重置 |
AddToCart 只读 variant;code review 时重点查 |
| 8 | 桌面 DataGridTemplateColumn 按钮点击干扰行选择/双击 | 按钮 Click 中 e.Handled = true;"+"按钮 Focusable=false 避免抢焦点 |
| 9 | 网页"+"按钮事件冒泡触发整行 onclick(带入选型) | ev.stopPropagation();抽屉面板内所有点击同样处理 |
| 10 | 角标件数与 BOM 数量语义混淆 | 定死:角标=行数,Qty 只在 BOM 体现(需求第 4 条) |
| 11 | 清单窗口关掉后数据丢失 | 购物车状态放主窗口/state,面板只是视图 |
| 12 | 打包中用户再点加入/删除导致 zip 内容快照不一致 | 打包开始时先对清单做快照(ToArray),打包期间 UI 允许操作但只影响下一次下载 |
九、交付物
- 两端可运行清单功能(bin\ 开发版 + 发布目录客户版 + 网页站)
web\libs\jszip.min.js(注明版本/来源/许可 MIT)src\App\Cart.cs+ MainWindow/网页改动(注释风格与现有一致)- 文档回写:项目总览(进展记录 + 踩坑 + 最后更新行)、维护手册、数据维护说明书(批量导出流程)
- 本文件验收标准逐条核对结果
十、不做的事(范围外)
- 不做清单持久化(网页刷新/软件重启即清空;若要跨会话保留,用 localStorage/文件另立项)
- 不做价格/报价单/订单/账号对接(BOM 只是清单文本)
- 不做网页服务端打包(保持纯静态)
- 不改选型核心逻辑、数据管线、.opc 格式