怎么用 这是格式与深度的参考,不是让你照抄的模板。数字全部是示例,直接抄进简历一问就穿——必须换成你自己的真实数据,而且要能说清是怎么测出来的。下面每个模块都有「数字是怎么测的」和「面试追问」两段,写不出那两段的模块就不要往简历上写

面试题库(电商 / 短视频 / 社区 / 本地生活 / 旅游 / 企业服务 多业务场景)

项目背景设定 跨境电商的商品与营销配置后台,Vue 3 + TypeScript + Pinia + Element Plus。使用者是商品运营与营销运营,日常工作是上架商品、维护 SKU、配活动。他们不是技术人员,但对效率极其敏感——一个商品要填几十个 SKU,一天上几百个商品。商品与 SKU 的后端模型在 电商 · 后端 · 虚拟商品交易平台,营销规则引擎在 营销与优惠券
为什么选这三个模块 这一页讲的是「给专业用户做高密度录入界面」这一类前端工作,它和 C 端页面的难点完全不同:C 端追求首屏与转化,这里追求的是「让一个熟练工每天少点几千次鼠标」。三个模块分别是三类硬骨头:SKU 矩阵编辑器(规格笛卡尔积生成的动态表格,改规格时不能丢已填数据,这是整页最难的一块)、营销规则的可试算配置(运营脑子里算不出叠加优惠的结果,得让他看见)、大列表的批量操作(跨页选择的语义陷阱、部分失败、可撤销)。大表格的虚拟滚动与异步导出在 多业务通用 · 运营管理后台 那一页,这里不重复。

模块一:SKU 矩阵编辑器

  1. SKU 矩阵编辑器(规格笛卡尔积动态生成 + 改规格保留已填数据 + 整列与阶梯批量填充 + 粘贴导入 + 校验定位到单元格)★★★
    简历这样写 商品 SKU 矩阵编辑器(规格笛卡尔积动态生成表格 + 以规格值组合为稳定键做增量 diff 保留已填数据 + 删除规格前的影响面确认 + 整列与阶梯批量填充与剪贴板粘贴导入 + 校验结果定位并滚动到具体单元格 + 本地草稿自动保存):运营维护一个商品需填写数十行 SKU,早期每次调整规格都重新生成表格、已填数据全部丢失,运营被迫先想好所有规格再动手;改为以规格值组合作为稳定键做增量 diff,新增规格值只追加行、删除规格值前先提示将影响多少行已填数据;提供整列填充、按规格阶梯填充、从表格软件直接粘贴三种批量录入方式(粘贴是运营的既有习惯,直接支持而非要求改流程);表单校验逐单元格定位并自动滚动聚焦,替代原先只提示「校验失败」的做法;同时按商品维度本地草稿自动保存,异常退出可恢复。改造后规格调整不再丢失已填数据,单商品录入的鼠标与键盘操作次数由逐格填写降为整列批量或一次粘贴
    展开完整拆解
    为什么要这么设计

    一件商品的 SKU 是规格的笛卡尔积:颜色 3 种 × 尺码 5 种 × 材质 2 种就是 30 个 SKU,每个都要填价格、库存、条码、重量、图片。也就是运营要在一个界面里填 30 行 × 5 列 = 150 个字段。这就是整页最核心的场景。

    第一版的实现很直接:运营勾选规格值,前端按笛卡尔积生成表格,运营逐格填写,保存。功能上没错,但运营用了一周就来投诉,问题集中在三点。

    第一个也是最严重的:改规格就丢数据。运营填了 30 行,突然想起还有一个颜色没加,勾上之后表格重新生成,刚填的 30 行全空了。因为实现是「规格变化 → 重算笛卡尔积 → 替换整个表格数据」。结果运营养成了一个习惯:先在纸上把所有规格想好再动手,因为一旦动手就不能改。这已经不是体验问题,是工具把人的工作方式扭曲了。

    根因是没有稳定的行标识。表格数据是按数组下标存的,规格一变下标就全错位了。正确做法是用「规格值组合」作为行的稳定键(比如「红色 / L / 棉」),规格变化时做 diff 而不是替换:新组合追加空行,消失的组合移除,已存在的组合原样保留。这一个改动就解决了最大的痛点。

    删除规格值需要额外处理:删掉一个尺码,会连带删掉 6 行已填数据。不能静默删除,要先告诉运营「这会删除 6 行已填写的 SKU」,让他确认。

    第二个投诉是逐格填写太慢。30 行的价格往往只有两三个档位(按尺码分档),但运营要点 30 次、输入 30 次。观察他们的实际工作后发现,很多人的真实做法是先在表格软件里排好再一个个抄进来——这个信息很关键,它说明我们该做的不是「优化输入框」,而是直接支持粘贴。所以做了三种批量填充:整列填同一个值按某个规格维度阶梯填充(所有 L 码填一个价)、从剪贴板粘贴整块数据顺着用户已有的习惯做,而不是要求他改流程。

    第三个投诉是校验报错找不到位置。150 个字段里有一个填错,第一版只弹一句「表单校验失败」。运营要自己一格格找。改成校验结果逐单元格标红,并自动滚动聚焦到第一个错误格,同时在顶部给出「共 3 处错误」的可点击列表。

    最后还补了一个本地草稿:填半小时的表单,浏览器崩了或者误点了返回,全部重填是灾难。按商品维度自动存本地草稿,重进时提示恢复。

    整体链路
    规格选择 → 表格生成(关键:diff 而不是替换) │ ├─ 运营勾选规格值 │ 颜色 3 × 尺码 5 × 材质 2 = 30 行 │ ├─ 行的稳定键 = 规格值组合,如「红色/L/棉」 │ 绝不能用数组下标做键 │ → 下标做键时规格一变全部错位,数据就丢了 │ ├─ 规格变化时做 diff │ 新出现的组合 → 追加空行 │ 消失的组合 → 移除 │ 已存在的组合 → 原样保留(这一条是重点) │ └─ 删除规格值前先算影响面 「这会删除 6 行已填写的 SKU」→ 要确认 不能静默删除 批量填充(顺着运营已有的习惯做) │ ├─ 整列填充:一个值填满整列 │ ├─ 阶梯填充:按某个规格维度分档 │ 所有 L 码填一个价,所有 XL 填另一个价 │ ├─ 剪贴板粘贴:从表格软件直接粘贴整块 │ 观察发现运营本来就在表格软件里排好再抄 │ → 该做的不是优化输入框,是直接支持粘贴 │ └─ 粘贴要处理 列数不匹配 → 提示而不是静默截断 粘贴区域超出行数 → 询问是否忽略多余部分 数字带货币符号、千分位 → 清洗后再校验 校验(150 个字段,报错必须能定位) │ ├─ 逐单元格校验并标红 ├─ 顶部汇总「共 N 处错误」,可点击跳转 ├─ 自动滚动聚焦到第一个错误单元格 │ └─ 只弹「表单校验失败」等于让运营自己找 这是第一版被投诉最多的点之一 草稿(半小时的输入不能因为一次误操作全丢) ├─ 按商品维度自动存本地草稿,节流写入 ├─ 重新进入时提示「有未保存的草稿,是否恢复」 ├─ 保存成功后清除草稿 └─ 草稿要带时间戳与规格快照 规格已变时要提示草稿可能不完整 提交 ├─ 只提交有变化的行(diff 后的增删改) ├─ 服务端仍要全量校验,前端校验只是体验优化 └─ 提交失败要保留输入,不能清空表格
    分步拆解
    1. 先确定行的稳定键是「规格值组合」,绝不用数组下标。这是整个模块的地基。下标做键时规格一变全部错位,已填数据就丢了——这是第一版最严重的问题。
    2. 规格变化时做 diff 而不是重新生成。新组合追加空行、消失的组合移除、已存在的组合原样保留
    3. 删除规格值前先算影响面并要求确认。「这会删除 6 行已填写的 SKU」——静默删除会让运营在不知情的情况下丢数据
    4. 提供整列填充。最简单也最常用,一个值填满整列。
    5. 提供按规格维度的阶梯填充。「所有 L 码填一个价」——因为真实的定价通常是按某一个维度分档的,不是每个组合都不同。
    6. 支持从表格软件直接粘贴整块数据。这一条来自观察而不是需求文档:运营本来就在表格软件里排好再一个个抄进来。顺着用户已有的习惯做,而不是要求他改流程。
    7. 粘贴要处理边界:列数不匹配要提示而不是静默截断。静默截断会让运营以为填好了,实际少了一列。
    8. 粘贴的数据要清洗:货币符号、千分位、全角字符。从表格软件复制出来的数字经常带格式,不清洗就会全部校验失败,运营会以为功能坏了
    9. 校验要逐单元格标红,不能只弹一句「表单校验失败」。150 个字段里让运营自己找错,这是第一版被投诉最多的点之一。
    10. 顶部给出「共 N 处错误」的可点击列表,并自动滚动聚焦第一个错误格。让运营能顺着列表一个个改完。
    11. 按商品维度自动存本地草稿,节流写入。填半小时的表单因为误点返回全丢是灾难。
    12. 草稿要带时间戳与规格快照,恢复时校验规格是否已变。规格变了草稿可能不完整,要提示而不是直接灌进去。
    13. 保存成功后清除草稿。否则下次进来还提示恢复一份旧数据,运营会困惑。
    14. 提交时只发有变化的行。全量提交在 SKU 多时既慢又容易触发并发覆盖。
    15. 前端校验只是体验优化,服务端必须全量校验。前端校验可以被绕过,这条底线不能松。
    关键决策与取舍

    用规格值组合做行键,而不是用后端返回的 SKU ID。后端 ID 更「正规」,但新建商品时行还没有 ID,而恰恰是新建场景下规格调整最频繁。所以行键必须是前端可以自己算出来的东西,也就是规格值组合。代价是规格值改名时组合键会变(把「红色」改成「大红」),这时要做一次键迁移。缓解手段是规格值内部也有稳定 ID,组合键用 ID 而不是名称拼成,展示时才映射为名称。这个细节值得讲,因为它说明「稳定键」的选择要经得住重命名。

    删除规格值时提示影响面,而不是禁止删除或静默删除。禁止删除会逼运营重建整个商品;静默删除会让人丢数据而不知情。提示加确认是唯一合理的中间态。这和运营后台里所有批量破坏性操作的处理是同一条原则——不禁止危险操作,但让它无法在不知情的情况下发生

    支持粘贴的决定,是从观察用户行为得来的,不是从需求文档。需求文档写的是「优化 SKU 录入效率」,如果只按文档做,大概会去优化输入框的 tab 顺序、加个快捷键。而实际观察发现运营在用表格软件当草稿纸,那么最大的效率提升就是让数据能直接搬进来。我认为这是这个模块最值得说的一点:面向专业用户的工具,需求要靠观察真实操作得出,用户自己往往只会提「太慢了」。

    踩过的坑:表格数据按数组下标存,规格一变全部错位。运营填完 30 行后新增一个颜色,diff 逻辑按下标比对,结果新行插在中间导致后面所有行的数据整体串位——比全部清空更糟,因为运营不一定立刻发现,可能把错的数据保存了。是有一次红色 XL 的价格出现在蓝色 S 上才发现的。修法是改用规格值组合作为稳定键教训是:任何会被增删的列表,键必须来自数据本身的业务标识,不能来自它在数组里的位置——这条在 Vue 的 v-for key、在长列表复用、在表格编辑上都是同一个问题。

    踩过的坑二:粘贴进来的数据全部校验失败,运营以为功能是坏的。从表格软件复制的价格带着千分位逗号和货币符号,我们直接拿去做数字校验,30 行全红。运营的反馈是「粘贴功能没用」,差点被要求下掉。修法是粘贴时做数据清洗(去货币符号、千分位、全角转半角、去首尾空格)再校验。教训是:导入类功能的容错要按「用户真实会粘什么」来设计,而不是按「理想格式」来设计——理想格式的导入功能等于没有导入功能。

    踩过的坑三:本地草稿没带规格快照,恢复后数据对不上规格。运营存了草稿,之后在别的地方改了商品规格,回来恢复草稿时把旧规格的数据灌进了新表格,行对不上。修法是草稿存规格快照,恢复前比对,不一致时提示「规格已变更,草稿可能不完整」并让用户选择教训是:草稿恢复必须校验上下文是否还成立,无条件恢复的草稿在数据结构变化后是有害的。

    踩过的坑四:校验只弹一句「表单校验失败」。这个坑的代价被严重低估了——150 个字段找一处错,运营平均要花几分钟,而这是每天几百次的操作。修法是逐格标红加错误列表加自动聚焦。教训是:高密度录入界面里,「定位错误」和「校验正确」同等重要,校验规则写得再全,报错不能定位就等于把工作推回给用户。

    没做的部分:没做 SKU 图片的批量上传与自动匹配(按文件名自动对应到规格组合)。运营提过,但文件名规范无法约束,匹配错的代价比手工上传更高。也没做 SKU 表格的列自定义(隐藏不常用的列),当时列数还在可接受范围。

    数字是怎么测的

    规格调整不丢数据:确定性验证。构造场景——填满 30 行后新增一个规格值、删除一个规格值、重命名一个规格值,分别检查已填数据是否原样保留、是否有串位串位这一项必须单独验,因为它比清空更隐蔽(我们就是靠「红色 XL 的价格出现在蓝色 S 上」才发现的)。

    录入效率:操作次数而不是耗时——「填 30 行价格从 30 次点击加 30 次输入,变为一次整列填充或一次粘贴」。操作次数是可核查的、和人的熟练度无关的量;耗时依赖具体运营的手速,不同人差几倍,报了会被追问怎么测的。

    粘贴成功率:粘贴后需要人工修正的字段数,改造前后对比(加数据清洗之前几乎全部要改)。也可以报「粘贴功能的使用率」——使用率能证明这个功能真的解决了问题,而不是做了没人用

    校验定位:这个用定性描述加操作次数:改造前运营要在 150 个字段里自己找,改造后点错误列表直接跳到出错单元格。不要编一个「查错时长下降 N%」,那需要一个改造前的准确基线,而改造前压根没有埋点。

    草稿恢复:草稿被实际使用(点击恢复)的次数。这个数字证明它真的在救人,而不是白做。同时要报规格已变导致提示不完整的次数,说明上下文校验在生效。

    不要报「录入效率提升 300%」。这个数字无法核查——效率的分母是什么、测了几个人、商品复杂度如何,全都说不清。正确表述是「操作次数从多少降到多少、支持了哪三种批量填充、哪些正确性由确定性用例保证」也不要报「零数据丢失」,本地草稿依赖浏览器存储,清缓存就没了,绝对化说法一问就穿。

    面试追问
    Q:SKU 表格是规格的笛卡尔积,运营中途改规格怎么办? A:做 diff 而不是重新生成,关键是行要有稳定键,键取「规格值组合」。第一版的实现是「规格变化 → 重算笛卡尔积 → 替换整个表格数据」,运营填了 30 行后新增一个颜色,刚填的全空了。结果运营养成了一个习惯:先在纸上把所有规格想好再动手,因为一旦动手就不能改——这已经不是体验问题,是工具把人的工作方式扭曲了。改法是用规格值组合(如「红色/L/棉」)作为行的稳定键,规格变化时做 diff:新组合追加空行、消失的组合移除、已存在的组合原样保留还有一个更隐蔽的坑:早期数据按数组下标存,新行插在中间导致后面所有行整体串位——比全部清空更糟,因为运营不一定立刻发现,可能把错的数据保存了,我们是靠「红色 XL 的价格出现在蓝色 S 上」才发现的教训是任何会被增删的列表,键必须来自数据本身的业务标识,不能来自它在数组里的位置。
    Q:稳定键用规格值组合,那规格值改名了怎么办? A:所以组合键要用规格值的稳定 ID 拼成,而不是用名称拼成,展示时才映射为名称。这个细节我觉得很值得说——如果键是「红色/L/棉」这样的名称拼接,运营把「红色」改成「大红」时所有行的键都变了,等于全部数据丢失,和第一版的问题一模一样,只是触发条件不同。用 ID 拼成的键(如「c1/s2/m1」)对重命名免疫。那为什么不直接用后端的 SKU ID 做行键:因为新建商品时行还没有后端 ID,而恰恰是新建场景下规格调整最频繁,行键必须是前端能自己算出来的东西。这里的判断是:稳定键的选择要经得住三种变化——增删、重排、重命名。我会按这三条去检验任何一个 key 的设计,包括 Vue 里 v-for 的 key、长列表组件复用的 key、表格编辑的行键,它们本质是同一个问题。
    Q:填 30 行 SKU 太慢,怎么优化录入效率? A:我做了三种批量填充,但我更想讲的是这个需求是怎么得出的。需求文档写的是「优化 SKU 录入效率」——如果只按文档做,大概会去优化输入框的 tab 顺序、加快捷键。但实际观察运营的操作后发现,很多人是先在表格软件里排好再一个个抄进来,表格软件在当草稿纸用。那么最大的效率提升就是让数据能直接搬进来。所以做了:整列填充(一个值填满整列)、按规格维度阶梯填充(所有 L 码填一个价,因为真实定价通常按某一个维度分档)、从表格软件直接粘贴整块数据顺着用户已有的习惯做,而不是要求他改流程。粘贴这里踩过一个差点让功能被下掉的坑:从表格软件复制的价格带千分位逗号和货币符号,我们直接拿去做数字校验,30 行全红,运营反馈「粘贴功能没用」。加了数据清洗(去货币符号、千分位、全角转半角)才可用。教训是导入类功能的容错要按「用户真实会粘什么」设计,而不是按「理想格式」设计——理想格式的导入功能等于没有导入功能。
    Q:150 个字段里有一个填错了,用户怎么找到? A:逐单元格标红 + 顶部错误列表可点击跳转 + 自动滚动聚焦第一个错误格。第一版只弹一句「表单校验失败」,这个坑的代价被我们严重低估了——150 个字段找一处错,运营平均要花几分钟,而这是每天几百次的操作,累积起来非常可观,也是被投诉最多的点之一。教训是:高密度录入界面里,「定位错误」和「校验正确」同等重要,校验规则写得再全,报错不能定位就等于把工作推回给用户。配套还做了本地草稿:填半小时的表单,浏览器崩了或误点返回全部重填是灾难,所以按商品维度自动存本地草稿并节流写入草稿这里也踩过坑:早期草稿没带规格快照,运营存了草稿后在别处改了商品规格,回来恢复时把旧规格的数据灌进了新表格,行对不上。修法是草稿存规格快照,恢复前比对,不一致就提示「规格已变更,草稿可能不完整」让用户选草稿恢复必须校验上下文是否还成立,无条件恢复在数据结构变化后是有害的。

模块二:营销规则配置与实时试算

  1. 营销规则配置与实时试算(动态规则表单 + 试算器让结果可见 + 叠加冲突与破价检测 + 请求竞态处理)★★★
    简历这样写 营销规则配置台与优惠试算器(按条件类型动态渲染的规则表单 + 假想订单实时试算并展示优惠明细 + 与在架活动的叠加冲突与破价预检 + 试算请求防抖与竞态丢弃 + 规则草稿与发布前二次确认):运营配置的优惠规则叠加后结果难以在脑中推演,早期只能配完上线再观察,出现过叠加后实付低于成本的情况;因此在配置页内置试算器——运营输入假想订单即实时返回优惠明细与最终实付(逐条列出命中的规则与各自减免额,而非只给总价);发布前做叠加冲突与破价预检,与在架活动做组合推演并对触及成本线的组合阻断发布并列出具体组合;规则表单按条件类型动态渲染字段并统一校验,试算请求防抖并按序号丢弃过期响应避免结果错乱。上线后叠加破价由发布前预检阻断而非上线后观察,运营配置的返工次数由试算可见性显著收敛
    展开完整拆解
    为什么要这么设计

    营销规则的配置界面,难点不在表单本身,而在「运营配完之后不知道自己配出了什么」

    一笔订单可能同时命中:会员折扣、满减、优惠券、限时秒杀、新客立减。这些规则叠加之后的实付金额,运营在脑子里是算不出来的——尤其还涉及优惠是否互斥、计算顺序、是否作用于同一个基数。第一版的做法是「配完发布,然后自己下单试试」,或者更糟:发布之后看数据发现不对再改

    我们出过一次事:一个满减和一张优惠券叠加后,某个商品的实付低于成本价。不是规则引擎算错了,是运营配的时候没想到这两个会叠在一起。发现是靠财务看毛利异常,那时已经卖了半天。

    所以这个模块的核心不是表单,是「让结果可见」。做了两件事。

    第一是试算器:在配置页里直接放一个「假想订单」输入区,运营填商品、数量、用户身份(是否会员、是否新客),实时调服务端算一遍,把优惠明细逐条列出来——命中了哪些规则、每条各减了多少、最终实付多少。关键是要给明细而不是只给总价:只给总价的话运营看到一个数字仍然不知道哪条规则起了作用,出问题时也不知道该改哪条。

    为什么试算必须调服务端而不是前端自己算:因为一旦前端有一套计算逻辑,它就会和服务端的规则引擎分叉,而分叉的试算器比没有试算器更危险——运营会信任它。这条判断和「可售性判定收敛为单一入口」是同一个思路。

    第二是发布前的冲突与破价预检:拿这个新规则和当前在架的所有活动做组合推演,找出「叠加后触及成本线」的组合,阻断发布并把具体组合列出来。运营看到的不是「有冲突」,而是「商品 A 在新客 + 这张券 + 你这个满减下实付 X,低于成本 Y」。

    另外两个工程细节值得说。

    规则表单是动态的:条件类型不同,需要的字段完全不同(「满 N 元减 M 元」要两个金额,「指定商品打折」要商品选择器加折扣率,「前 N 件半价」要件数)。所以表单不能写死,要按条件类型的元数据动态渲染字段并统一校验

    试算的请求竞态:运营一边改规则一边看试算结果,输入是连续的。如果不处理,先发的请求后回来,会把新的结果覆盖成旧的——运营看到的是一个和当前配置不匹配的金额,这比不给结果更糟。所以要防抖加请求序号,只接受最新那次的响应

    整体链路
    规则表单(按条件类型动态渲染) │ ├─ 条件类型的元数据决定要渲染哪些字段 │ 满 N 元减 M 元 → 两个金额输入 │ 指定商品打折 → 商品选择器 + 折扣率 │ 前 N 件半价 → 件数输入 │ ├─ 表单不写死,按元数据生成 + 统一校验 │ 写死的话每加一种活动类型都要改页面 │ └─ 规则草稿本地保存,配置过程可能很长 试算器(这个模块的核心:让结果可见) │ ├─ 运营输入假想订单 │ 商品与数量 │ 用户身份:是否会员 / 是否新客 │ 可选的券 │ ├─ 调服务端算,不在前端自己算 │ 前端自己算 → 必然和规则引擎分叉 │ → 分叉的试算器比没有试算器更危险 │ → 因为运营会信任它 │ ├─ 返回并展示优惠明细,不只给总价 │ 命中了哪些规则 │ 每条各减了多少 │ 计算顺序 │ 最终实付 │ → 只给总价,运营仍不知道该改哪条 │ └─ 请求竞态处理 防抖:输入停止后再发 请求序号:只接受最新那次的响应 → 否则先发的后回来,把新结果覆盖成旧的 → 运营看到与当前配置不匹配的金额,比不给更糟 发布前预检(把「上线后发现」提前到「发布前阻断」) │ ├─ 取当前在架的所有活动 ├─ 与新规则做组合推演 │ ├─ 检测叠加破价 │ 某组合下实付触及或低于成本线 → 阻断发布 │ ├─ 检测互斥配置矛盾 │ 规则 A 声明与 B 互斥,B 未声明与 A 互斥 │ └─ 报错要给具体组合,不能只说「有冲突」 「商品 A 在 新客 + 券X + 你这个满减 下实付 N,低于成本 M」 → 运营才知道要改什么 发布 ├─ 二次确认,展示生效范围与时间 ├─ 支持定时生效与紧急下线 └─ 发布记录留痕:谁在什么时候发了什么规则
    分步拆解
    1. 先认清这个模块的难点不在表单,在「运营配完不知道自己配出了什么」。会员折扣、满减、券、秒杀、新客立减叠加后的实付,运营在脑子里算不出来
    2. 规则表单按条件类型的元数据动态渲染字段。不同活动类型需要的字段完全不同,写死的话每加一种活动都要改页面
    3. 动态表单的校验也要统一由元数据驱动。否则字段是动态的、校验是写死的,加类型时一定会漏。
    4. 在配置页内置试算器,输入假想订单。商品、数量、用户身份(会员、新客)、可选的券。
    5. 试算必须调服务端算,绝不在前端自己实现一套。前端自己算必然和规则引擎分叉,而分叉的试算器比没有试算器更危险——因为运营会信任它。
    6. 试算结果要给优惠明细,不能只给总价。命中了哪些规则、每条减了多少、计算顺序。只给总价,运营看到一个数字仍不知道该改哪条。
    7. 试算请求要防抖。运营一边改一边看,输入是连续的,不防抖会打出大量无用请求。
    8. 试算请求要带序号并丢弃过期响应。否则先发的请求后回来会把新结果覆盖成旧的,运营看到与当前配置不匹配的金额,这比不给结果更糟
    9. 发布前做叠加预检:取在架活动与新规则做组合推演。把「上线后靠数据发现」提前到「发布前阻断」。
    10. 检测叠加破价:某组合下实付触及成本线就阻断发布。我们出过事——满减加券叠加后实付低于成本,财务看毛利异常才发现,那时已经卖了半天
    11. 检测互斥声明的矛盾。规则 A 声明与 B 互斥但 B 没声明与 A 互斥,这类单边声明会导致实际行为取决于计算顺序。
    12. 预检报错要给具体组合,不能只说「有冲突」。要说到「商品 A 在新客加券 X 加你这个满减下实付多少、低于成本多少」,运营才知道要改什么
    13. 发布要二次确认并展示生效范围与时间。营销规则的影响面通常很大,发布前让人看一眼范围。
    14. 支持定时生效与紧急下线。紧急下线是必需的——出问题时第一步是止损而不是改规则。
    15. 发布记录留痕:谁在什么时候发了什么规则。复盘和追责都要用。
    关键决策与取舍

    试算调服务端而不是前端算,代价是每次输入都要一次网络往返。前端算的好处很直观:即时、无网络开销、无竞态问题。但它有一个致命缺陷——前端必须复制一份规则计算逻辑,而这份复制品会随着规则引擎演进而分叉。分叉之后试算器给出的是错的答案,而运营已经信任它了,这比没有试算器更危险。所以选服务端算,用防抖加请求序号把网络开销和竞态问题解决掉。这条判断和「可售性判定收敛为单一入口」「价格一律服务端重算」是同一条线:同一个业务计算不能有两份实现。

    破价预检做成「阻断发布」而不是「警告」。警告的问题是它会被习惯性忽略——运营每天配几十个活动,看到黄色提示直接点确定。而破价的后果是真金白银的损失,属于不可逆。所以对触及成本线的组合直接阻断,要发布必须先改规则或者显式申请例外(走审批)。取舍是偶尔会阻断一个业务上确实想做的亏本引流活动,缓解手段是提供「例外申请」的正规出口而不是把阻断改成警告——有出口的阻断优于会被忽略的警告。

    踩过的坑:满减和优惠券叠加后实付低于成本,卖了半天才发现。不是规则引擎算错,是运营配的时候没想到这两个会叠在一起。发现路径是财务看毛利异常。修法是发布前的组合预检教训是:配置类系统的风险主要来自「配置者的认知盲区」而不是「系统的计算错误」——所以投入方向应该是让配置结果可见、让危险组合被提前发现,而不是继续加强计算逻辑的正确性(它本来就是对的)。

    踩过的坑二:试算请求竞态,运营看到与配置不匹配的金额并按它做了决策。运营连续调整满减门槛,先发的请求后返回,试算区显示的是上一次配置的结果,运营以为当前配置算出来是这个数,就发布了。结果上线后的实际优惠和他看到的不一样。修法是请求带序号,只接受最新那次的响应,并且在等待期间把结果区置为加载态而不是保留旧值教训是:异步结果的展示必须能表达「正在算」这个中间态,保留旧值的做法在语义上是在撒谎。

    踩过的坑三:试算只给总价,运营调了半天不知道该改哪条规则。试算器上线后运营反馈「知道结果不对但不知道问题在哪」。修法是返回并展示逐条优惠明细与计算顺序教训是:诊断类工具的价值在于「指出原因」而不是「给出结论」,只给结论的工具会让用户陷入试错循环。

    踩过的坑四:动态表单的字段是元数据驱动的,但校验规则写死在页面里。新增一种活动类型时字段自动出来了,校验却没跟上,运营配了一个折扣率填 150% 的活动并且发布成功了。修法是校验规则也放进元数据,和字段定义一起下发教训是:动态渲染和动态校验必须同源,一半动态一半写死,等于给自己埋一个「加类型时必漏」的坑。

    没做的部分:没做历史订单回放式试算(拿过去一段真实订单跑一遍新规则,看整体让利额与毛利影响)。这是运营真正想要的能力,但需要拉取大量历史订单并批量试算,属于后端与数据侧的工作量,当时只做了单笔假想订单。也没做规则的可视化编排(把叠加与互斥关系画成图),只做了列表加声明式配置。

    数字是怎么测的

    破价预检的效果:发布前被阻断的次数与阻断原因。最有说服力的表述是「上线以来阻断 N 次触及成本线的组合,其中 M 次运营确认是配置失误」——后半句很关键,它证明阻断不是误报。同时要主动报误阻断(业务上确实想做的亏本引流)的次数与走例外审批的比例。

    试算器的使用率:发布前使用过试算的活动占比这个数字比任何自述都能证明功能有用——如果使用率很低,说明它没解决真问题或者入口太深。

    配置返工次数:活动发布后被修改或紧急下线的次数,改造前后对比。这是「结果可见」带来的直接业务收益。要说明统计口径(发布后 24 小时内的修改算返工),否则数字没法核查。

    竞态问题:确定性验证——连续快速修改规则触发多次试算,检查展示的始终是最后一次配置对应的结果,且等待期间显示加载态而不是旧值。这类问题用确定性用例覆盖。

    试算响应耗时:要主动报,因为选了服务端计算就必须回答「会不会卡」。给出防抖间隔与试算接口的 P95,说明为什么选服务端算并接受这个延迟

    不要报「优惠计算准确率 100%」。计算是服务端规则引擎做的,不是这个前端页面的成果,报了会被追问「那是你做的吗」。也不要报「零破价」——例外审批允许亏本活动存在,绝对化说法自己就矛盾。正确表述是「预检阻断了多少次、试算使用率多少、发布后返工次数的变化、竞态由确定性用例保证」。

    面试追问
    Q:运营配了一堆优惠规则,怎么让他知道最终会算出什么价? A:在配置页里内置试算器,让运营输入假想订单实时看结果——这个模块的核心不是表单,是「让结果可见」。一笔订单可能同时命中会员折扣、满减、券、秒杀、新客立减,叠加之后的实付运营在脑子里算不出来,第一版的做法是「配完发布,然后自己下单试试」,或者更糟:上线后看数据发现不对再改。试算器有两个设计要点。一是必须调服务端算,绝不在前端自己实现一套——前端算的好处是即时无延迟,但它要复制一份规则计算逻辑,而这份复制品会随规则引擎演进而分叉,分叉的试算器比没有试算器更危险,因为运营已经信任它了二是要给优惠明细而不是只给总价:命中了哪些规则、每条减了多少、计算顺序。我们踩过这个坑——试算器上线后运营反馈「知道结果不对但不知道问题在哪」。教训是诊断类工具的价值在于「指出原因」而不是「给出结论」,只给结论会让用户陷入试错循环。
    Q:两个活动叠加导致亏本卖,怎么提前发现? A:发布前做组合预检,把「上线后靠数据发现」提前到「发布前阻断」。我们出过一次事:一个满减和一张优惠券叠加后某个商品实付低于成本价,不是规则引擎算错,是运营配的时候没想到这两个会叠在一起,发现路径是财务看毛利异常,那时已经卖了半天。修法是取当前在架的所有活动,与新规则做组合推演,找出触及成本线的组合。两个设计决定值得说。一是做成「阻断发布」而不是「警告」——警告会被习惯性忽略(运营每天配几十个活动,看到黄色提示直接点确定),而破价的后果是真金白银且不可逆;取舍是偶尔会阻断业务确实想做的亏本引流活动,缓解手段是提供「例外申请走审批」这个正规出口,而不是把阻断降级成警告——有出口的阻断优于会被忽略的警告二是报错要给具体组合:「商品 A 在新客加券 X 加你这个满减下实付多少、低于成本多少」,而不是只说「有冲突」。教训是:配置类系统的风险主要来自配置者的认知盲区,而不是系统的计算错误。
    Q:运营一边改规则一边看试算,请求会不会乱? A:会,而且我们踩过,后果比想象的严重。运营连续调整满减门槛,先发的请求后返回,试算区显示的是上一次配置的结果,运营以为当前配置算出来是这个数就发布了,结果上线后的实际优惠和他看到的不一样。修法两条:防抖(输入停止后再发,避免打出大量无用请求)加请求序号只接受最新那次的响应;还有一条容易被忽略的——等待期间要把结果区置为加载态,而不是保留旧值教训是异步结果的展示必须能表达「正在算」这个中间态,保留旧值的做法在语义上是在撒谎:界面上有一个看起来有效的数字,而它对应的是已经不存在的配置。这个判断我在别的地方也用——筛选条件改了但列表还是旧结果、搜索词改了但结果没跟上,都是同一类问题,解法都是「序号丢弃 + 明确的加载态」。
    Q:活动类型很多,每种要填的字段都不一样,表单怎么做? A:按条件类型的元数据动态渲染字段,而且校验规则必须和字段定义同源。不同活动类型需要的字段完全不同:「满 N 元减 M 元」要两个金额输入、「指定商品打折」要商品选择器加折扣率、「前 N 件半价」要件数。写死的话每加一种活动类型都要改页面,而营销活动类型是持续增加的。我们踩过一个「一半动态一半写死」的坑:字段是元数据驱动的,但校验规则写死在页面里,新增一种活动类型时字段自动出来了、校验却没跟上,运营配了一个折扣率填 150% 的活动并且发布成功了。修法是把校验规则也放进元数据,和字段定义一起下发教训是动态渲染和动态校验必须同源,一半动态一半写死,等于给自己埋一个「加类型时必漏」的坑。另外配置过程可能很长,所以规则草稿也要本地保存——这和 SKU 表格的草稿是同一个需求,专业用户的长表单都需要这个。

模块三:批量操作与可撤销

  1. 批量操作与可撤销(跨页选择语义显式化 + 影响面前置确认 + 逐条结果与部分失败重试 + 撤销与回滚)★★★
    简历这样写 商品列表的批量操作与可撤销设计(「当页勾选」与「全部符合筛选」两种选择语义显式区分 + 执行前影响面量化确认 + 任务化执行与逐条结果记录 + 部分失败可单独重试 + 批次级撤销):批量改价与批量上下架的选择语义存在歧义——勾选表头复选框时用户以为选中的是「全部符合筛选条件的商品」而实现只选了当前页,反向的误解则会造成远超预期的影响,因此把两种语义显式拆成两个操作并各自展示预计条数;执行前量化影响面(将修改多少商品、其中多少存在特殊状态)并要求确认;执行采用任务化方式,逐条记录成功失败与原因,失败项可单独重试而无需整批重做;对改价类操作保留变更前值支持批次撤销。上线后批量误操作由影响面确认在执行前暴露,部分失败由逐条重试替代整批重做,改价失误可按批次回滚而无需逐条修复
    展开完整拆解
    为什么要这么设计

    商品列表是运营最常用的页面,批量操作是它的核心能力:批量上下架、批量改价、批量改类目、批量打标。这些操作看起来简单,但它们是运营后台里最容易造成事故的地方,因为一次点击影响成百上千条数据。

    第一版栽在跨页选择的语义歧义上。列表有分页,表头有一个全选复选框。用户点它的时候,心里想的是「选中所有符合当前筛选条件的商品」(因为他刚刚筛出了「某个类目下的所有商品」),而实现选的是「当前页的 20 条」

    于是运营筛出 800 个商品,点全选,点批量下架,以为下架了 800 个,实际只下架了 20 个。他检查了一下发现列表里还有很多,就翻页再点一遍,翻了几页觉得太累,去问客服「批量下架是不是坏了」。这个方向的误解只是效率问题。

    反方向的误解就是事故。另一个场景里我们做了「选中全部符合条件」的实现,运营以为只选了当前页,结果批量改价影响了几百个商品,其中很多他压根没看过。

    所以核心设计是把两种语义显式拆成两个操作,并且各自把条数写出来:一个是「已勾选 20 项」,另一个是「选中全部符合条件的 800 项」。不要试图用一个复选框表达两种语义,也不要靠文案暗示——直接给两个按钮,各自带上数字。

    第二个设计是执行前的影响面确认。不只报条数,还要报其中有多少处于特殊状态——比如批量下架时有多少商品正在参加活动、有多少有在途订单。这些是运营真正需要知道但列表上看不出来的信息。

    第三个是部分失败。几百条的批量操作不可能是一个事务,中间必然有失败(某个商品被别人锁了、某个商品状态不允许下架)。第一版的行为是抛一个错「批量操作失败」,运营不知道哪些成功了,只能整批重做,而重做会把已成功的又处理一遍。

    改成任务化:提交后生成一个任务,逐条记录成功失败与失败原因,界面上展示进度和结果列表,失败项可以单独重试

    第四个是撤销。改价这类操作填错一个数字(少打一个 0)后果很直接。所以改价类批量操作要保留变更前的值,支持按批次撤销。这个能力不复杂,但它把「运营不敢用批量改价」变成「敢用」。

    整体链路
    选择(两种语义,显式拆开,各带数字) │ ├─ 语义一:已勾选的当页项 │ 按钮文案「操作已勾选的 20 项」 │ ├─ 语义二:全部符合当前筛选条件的项 │ 按钮文案「操作全部符合条件的 800 项」 │ └─ 不要用一个复选框表达两种语义 也不要靠文案暗示 → 第一版的歧义造成两个方向的误解 以为选全部实际只选当页 → 效率问题 以为选当页实际选了全部 → 事故 执行前确认(不只报条数,报「看不出来的信息」) │ ├─ 将修改多少商品 ├─ 其中处于特殊状态的有多少 │ 正在参加活动的 │ 有在途订单的 │ 被其他人正在编辑的 │ ├─ 改价类还要报变化幅度 │ 「最大降幅 60%,涉及 12 个商品」 │ → 少打一个 0 会在这里露出来 │ └─ 这些是运营需要知道但列表上看不出来的 执行(任务化,不做成一个同步请求) │ ├─ 提交后生成任务,返回任务号 ├─ 前端轮询或订阅进度 ├─ 逐条记录:成功 / 失败 / 失败原因 │ ├─ 失败原因要具体 │ 「商品被锁定」「状态不允许下架」「无权限」 │ 而不是统一的「操作失败」 │ └─ 第一版抛一个「批量操作失败」 运营不知道哪些成功了,只能整批重做 而重做会把已成功的又处理一遍 结果与重试 ├─ 结果分成功列表与失败列表 ├─ 失败项可单独重试,不必整批重做 ├─ 失败列表可导出,方便线下核对 └─ 任务记录保留,可回溯「上周那次批量改价改了什么」 撤销(改价类必须有) ├─ 执行时保留每条的变更前值 ├─ 支持按批次整体撤销 ├─ 撤销本身也是一个任务,同样逐条记录 └─ 撤销要校验「当前值仍是我改的那个值」 否则会覆盖别人之后做的修改 并发保护 ├─ 提交时带列表查询的筛选条件与快照时间 ├─ 服务端校验数据在此期间是否被改动 └─ 「全部符合条件」的语义下这一点尤其重要 期间新增的商品是否要包含,必须有明确定义 期间新增的商品是否要包含,必须有明确定义
    分步拆解
    1. 先认清跨页选择存在两种语义,而且用户的理解会往两个方向偏。「已勾选的当页项」和「全部符合筛选条件的项」,用一个复选框表达两种语义必然出事
    2. 把两种语义拆成两个显式操作,并各自带上条数。「操作已勾选的 20 项」和「操作全部符合条件的 800 项」。不要靠文案暗示,直接给两个按钮加数字。
    3. 理解两个方向误解的代价不同。以为选全部实际只选当页 → 只是效率问题;以为选当页实际选了全部 → 是事故,因为影响了运营压根没看过的数据。
    4. 执行前量化影响面,不只报条数。还要报其中有多少处于特殊状态:正在参加活动的、有在途订单的、被其他人正在编辑的。
    5. 改价类操作还要报变化幅度。「最大降幅 60%,涉及 12 个商品」——少打一个 0 会在这里露出来,这是最有效的一道防线。
    6. 影响面确认要报「列表上看不出来的信息」。条数运营自己能数,但「有多少在参加活动」他看不出来,这才是确认弹窗的价值。
    7. 把批量执行做成任务,不要做成一个同步请求。几百条不可能是一个事务,同步请求必然超时。
    8. 逐条记录成功、失败与失败原因。第一版只抛一个「批量操作失败」,运营不知道哪些成功了,只能整批重做,而重做会把已成功的又处理一遍
    9. 失败原因要具体:「商品被锁定」「状态不允许下架」「无权限」。统一的「操作失败」让运营无从下手。
    10. 失败项可单独重试,不必整批重做。这是任务化最直接的收益。
    11. 失败列表可导出。几十条失败时运营需要线下核对,导出比在页面上翻更实际。
    12. 任务记录要保留可回溯。「上周那次批量改价到底改了什么」是复盘时的真实需求。
    13. 改价类操作必须保留变更前值并支持批次撤销。这个能力不复杂,但它把「运营不敢用批量改价」变成「敢用」
    14. 撤销时要校验「当前值仍是我改的那个值」。否则会覆盖别人在这之后做的修改
    15. 提交时带筛选条件与快照时间,服务端校验期间数据是否变动。「全部符合条件」的语义下,期间新增的商品是否包含必须有明确定义,不能含糊。
    关键决策与取舍

    把两种选择语义拆成两个按钮,而不是用一个复选框加文案说明。做成一个复选框加提示文字(「已选中当前页 20 项,点击选择全部 800 项」)是很常见的做法,也更省界面空间。但文案会被忽略,尤其是每天做几百次这个操作的熟练工——他的手比眼睛快。两个独立按钮各带数字,让用户在点击的那一刻就在数字上做出选择,而不是先点复选框再去读一行提示。取舍是占了更多界面空间、看起来不够简洁。我认为这个取舍值得:在破坏性操作上,明确胜过简洁。

    影响面确认报「特殊状态数」而不只是条数,这一条决定了确认弹窗有没有用。只报条数的弹窗会被无脑点确定,因为条数是用户自己筛出来的、他已经知道。而「其中 12 个正在参加活动」是他不知道的信息,这才让他真的停下来看一眼。这个判断可以推广:确认弹窗的价值取决于它是否提供了新信息,重复用户已知的信息只是增加一次点击。

    撤销只对改价这类「值型」操作做,不对上下架这类「状态型」操作做。状态型操作用户重新批量操作一次就行,代价低;而改价的原值是丢失的信息,不保留就再也找不回来。取舍是没有做统一的通用撤销框架,而是按「原值是否可恢复」来决定要不要保留快照——这样避免了为所有操作都存快照带来的存储与复杂度。

    踩过的坑:跨页选择语义歧义,同一个功能在两个方向都出了问题。一边是运营筛出 800 个点全选下架,以为下架了 800 实际只下架 20,翻了几页觉得累就去问客服「批量下架是不是坏了」;另一边是另一个列表实现成「选中全部符合条件」,运营以为只选了当前页,结果批量改价影响了几百个他压根没看过的商品。修法是显式拆成两个操作。教训是:当一个交互存在两种合理解读时,不要选一种去实现然后用文案解释,而要把两种都做成显式入口——用户的心智模型不会因为一行提示文字而改变。

    踩过的坑二:批量操作部分失败后整批重做,把已成功的又处理了一遍。一次批量下架有几十条失败,运营重新执行全部,而已成功下架的商品被再次「下架」,其中有几个在这期间被别人上架了,又被这次重做下架掉,造成了一次不该有的状态变更。修法是任务化加逐条结果加失败项单独重试教训是:批量操作必须记录每个个体的结果,否则失败后唯一的补救手段就是全量重做,而全量重做在有并发写入时会造成二次伤害。

    踩过的坑三:撤销没校验当前值,覆盖了别人之后的修改。运营批量改价改错了,点撤销回滚,但期间另一个运营已经把其中几个商品的价格改成了新的正确值,撤销把它们盖回了更早的旧值。修法是撤销时逐条校验「当前值仍等于我这次改成的值」,不等的跳过并列出来教训是:撤销不是简单地写回旧值,它是一次带前置条件的更新——条件就是「这个值还没被别人改过」。

    踩过的坑四:「全部符合条件」的语义下,期间新增的商品是否包含没有定义。运营点了「操作全部符合条件的 800 项」,执行期间又有新商品被创建并符合筛选条件,结果它也被处理了,运营完全不知道。修法是提交时带筛选条件与快照时间,服务端只处理快照时间之前的数据,并在结果里说明「期间新增 N 条未包含」教训是:基于查询条件的批量操作必须定义时间边界,「符合条件的全部」是一个随时间变化的集合,不锁定时间点就没有确定的语义。

    没做的部分:没做批量操作的定时执行与审批流(大额改价先走审批再执行)。运营侧有这个诉求,但需要接审批引擎,当时用「例外情况人工在群里确认」这个流程兜着。也没做操作的影响面模拟(改价后预计对 GMV 的影响),那需要预测模型,超出前端范围。

    数字是怎么测的

    误操作的拦截:影响面确认弹窗出现后被用户主动取消的次数这是最直接的证据——「有 N 次批量操作在看到影响面后被取消」证明确认不是走形式。同时可以报其中「因为看到降幅异常而取消」的占比,说明幅度提示这一项在起作用。

    选择语义的歧义:这个用客服工单数量来度量——改造前有「批量下架不生效」这类工单,改造后消失。工单数是外部的、可核查的证据,比自述有说服力。

    部分失败的处理:批量任务的成功数、失败数、失败原因分布、以及重试后的成功数关键是要能说出「失败项可单独重试」这个能力,而不只给一个成功率。

    撤销的使用:撤销被实际使用的次数,以及撤销时因「当前值已被他人修改」而跳过的条数。后者证明并发校验在生效——如果这个数一直是 0,要么并发确实不存在,要么校验没跑,得说清是哪种

    时间边界:确定性验证——执行「全部符合条件」的批量操作期间创建新的符合条件的数据,检查它没有被处理,且结果中说明了「期间新增 N 条未包含」

    不要报「批量操作成功率 99.9%」。失败大多来自业务状态(商品被锁、状态不允许),不是这个前端功能的成果也不要报「零误操作」——确认弹窗只能减少误操作,用户执意确认时仍会发生。正确表述是「两种选择语义显式化后相关工单消失、影响面确认拦下多少次、部分失败可逐条重试、改价可按批次撤销并带并发校验」。

    面试追问
    Q:列表分页了,用户点全选,是选当前页还是选全部? A:这个歧义我们在两个方向上都栽过,最后的答案是「显式拆成两个操作,各自带上条数」。一个方向:运营筛出 800 个商品点全选后批量下架,以为下架了 800,实际只下架了当前页 20 个,他翻页再点,翻几页觉得累就去问客服「批量下架是不是坏了」——这个方向只是效率问题。另一个方向:另一个列表实现成「选中全部符合条件」,运营以为只选了当前页,结果批量改价影响了几百个他压根没看过的商品——这个方向是事故修法是给两个按钮:「操作已勾选的 20 项」和「操作全部符合条件的 800 项」。为什么不用一个复选框加提示文案(更省空间、更常见):文案会被忽略,尤其是每天做几百次这个操作的熟练工——他的手比眼睛快。两个带数字的按钮让用户在点击那一刻就在数字上做出选择教训是:当一个交互存在两种合理解读时,不要选一种实现再用文案解释,而要把两种都做成显式入口——用户的心智模型不会因为一行提示而改变。
    Q:批量操作前的确认弹窗,很多人会无脑点确定,怎么让它有用? A:关键是弹窗必须提供用户不知道的新信息,否则它只是多一次点击。只报条数的弹窗一定会被无脑确认——条数是用户自己筛出来的,他已经知道。所以我们报的是「列表上看不出来的信息」:其中有多少商品正在参加活动、有多少有在途订单、有多少正被其他人编辑。改价类操作还额外报变化幅度——「最大降幅 60%,涉及 12 个商品」,少打一个 0 会在这里露出来,这是最有效的一道防线这个判断可以推广:确认弹窗的价值取决于它是否提供了新信息,重复用户已知的信息只会训练用户忽略它。验证方式也很直接:报确认弹窗出现后被用户主动取消的次数,以及其中「因为看到降幅异常而取消」的占比——如果取消次数常年是 0,说明弹窗确实只是走形式,该重新设计它给的信息。
    Q:批量操作做了一半失败了怎么办? A:任务化,逐条记录结果,失败项单独重试——不能让用户整批重做。第一版是抛一个「批量操作失败」,运营不知道哪些成功了,只能整批重做。我们踩过这个坑的后果:一次批量下架有几十条失败,运营重新执行全部,而已成功下架的商品被再次处理,其中几个在这期间被别人上架了,又被这次重做下架掉,造成了一次不该有的状态变更。教训是:批量操作必须记录每个个体的结果,否则失败后唯一的补救手段就是全量重做,而全量重做在有并发写入时会造成二次伤害。具体做法:提交后生成任务返回任务号,前端展示进度,逐条记录成功失败与具体原因(「商品被锁定」「状态不允许下架」「无权限」,而不是统一的「操作失败」),结果分成功与失败两个列表、失败可单独重试、失败列表可导出(几十条失败时运营需要线下核对),任务记录保留可回溯——「上周那次批量改价到底改了什么」是复盘时的真实需求。
    Q:批量改价改错了,能撤销吗? A:能,但撤销不是简单地写回旧值,它是一次带前置条件的更新。做法是执行时保留每条的变更前值,支持按批次撤销,撤销本身也是一个任务、同样逐条记录。这个能力不复杂,但它把「运营不敢用批量改价」变成「敢用」。我们踩过的坑是撤销没校验当前值:运营批量改价改错后点撤销,但期间另一个运营已经把其中几个商品改成了新的正确价格,撤销把它们盖回了更早的旧值。修法是撤销时逐条校验「当前值仍等于我这次改成的值」,不等的跳过并列出来告知另一个设计判断是:撤销只对改价这类「值型」操作做,不对上下架这类「状态型」操作做——状态型重新批量操作一次就行、代价低,而改价的原值是丢失的信息,不保留就再也找不回来按「原值是否可恢复」决定要不要存快照,这样避免了为所有操作都存快照的存储与复杂度成本。

没有匹配的内容,换个关键词试试。

项目拆解 · 商品与 SKU 配置台(Vue)· 共 3 个模块 · 数字均为示例,需替换成自己项目的真实数据