meituan-promotion-types-demo.html 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>美团商家促销类型解析</title>
  7. <style>
  8. * { margin: 0; padding: 0; box-sizing: border-box; }
  9. body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif; background: #f5f5f5; color: #333; padding: 16px; max-width: 480px; margin: 0 auto; }
  10. .page-title { text-align: center; font-size: 20px; font-weight: 700; margin: 12px 0 20px; color: #333; }
  11. /* Category Section */
  12. .category { background: #fff; border-radius: 12px; margin-bottom: 16px; overflow: hidden; box-shadow: 0 1px 4px rgba(0,0,0,0.08); }
  13. .category-header { padding: 14px 16px; display: flex; align-items: center; gap: 10px; }
  14. .category-header .icon { width: 36px; height: 36px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-size: 18px; color: #fff; flex-shrink: 0; }
  15. .category-header .info h3 { font-size: 16px; font-weight: 600; }
  16. .category-header .info p { font-size: 12px; color: #999; margin-top: 2px; }
  17. .cat-order .icon { background: linear-gradient(135deg, #ff6b35, #ff4500); }
  18. .cat-item .icon { background: linear-gradient(135deg, #4facfe, #2196f3); }
  19. .cat-delivery .icon { background: linear-gradient(135deg, #43e97b, #38b249); }
  20. .cat-coupon .icon { background: linear-gradient(135deg, #fa709a, #e91e63); }
  21. /* Promo Card */
  22. .promo-card { padding: 12px 16px; border-top: 1px solid #f0f0f0; }
  23. .promo-card .promo-title { font-size: 14px; font-weight: 600; margin-bottom: 6px; display: flex; align-items: center; gap: 6px; }
  24. .promo-card .promo-title .badge { font-size: 10px; padding: 1px 6px; border-radius: 3px; color: #fff; font-weight: 500; }
  25. .badge-auto { background: #ff6b35; }
  26. .badge-select { background: #2196f3; }
  27. .badge-manual { background: #e91e63; }
  28. .promo-card .promo-desc { font-size: 12px; color: #666; margin-bottom: 8px; line-height: 1.6; }
  29. .promo-card .example { background: #fff8f0; border-radius: 8px; padding: 10px 12px; font-size: 12px; }
  30. .cat-item .promo-card .example { background: #f0f7ff; }
  31. .cat-delivery .promo-card .example { background: #f0fff4; }
  32. .cat-coupon .promo-card .example { background: #fff0f5; }
  33. .example .label { color: #999; margin-bottom: 4px; }
  34. .example .calc { color: #333; line-height: 1.8; }
  35. .example .calc .price { color: #ff4500; font-weight: 600; }
  36. .example .calc .line-through { text-decoration: line-through; color: #999; }
  37. .example .calc .highlight { background: #fff3cd; padding: 0 3px; border-radius: 2px; }
  38. /* Interactive Demo */
  39. .demo-section { background: #fff; border-radius: 12px; margin-bottom: 16px; overflow: hidden; box-shadow: 0 1px 4px rgba(0,0,0,0.08); }
  40. .demo-header { padding: 14px 16px; background: linear-gradient(135deg, #667eea, #764ba2); color: #fff; }
  41. .demo-header h3 { font-size: 16px; font-weight: 600; }
  42. .demo-header p { font-size: 12px; opacity: 0.8; margin-top: 2px; }
  43. /* Order Items */
  44. .order-items { padding: 12px 16px; }
  45. .order-item { display: flex; justify-content: space-between; align-items: center; padding: 8px 0; border-bottom: 1px solid #f5f5f5; font-size: 13px; }
  46. .order-item:last-child { border-bottom: none; }
  47. .order-item .name { flex: 1; }
  48. .order-item .item-price { color: #333; font-weight: 500; min-width: 60px; text-align: right; }
  49. .order-item .item-final { color: #ff4500; font-weight: 600; min-width: 60px; text-align: right; }
  50. .order-item .item-tag { font-size: 10px; padding: 1px 5px; border-radius: 3px; color: #fff; margin-left: 6px; }
  51. .item-tag-discount { background: #2196f3; }
  52. .item-tag-normal { background: #ccc; }
  53. /* Calculation Steps */
  54. .calc-steps { padding: 0 16px 16px; }
  55. .calc-step { display: flex; justify-content: space-between; align-items: center; padding: 6px 0; font-size: 13px; }
  56. .calc-step .step-label { color: #666; display: flex; align-items: center; gap: 6px; }
  57. .calc-step .step-label .step-icon { width: 20px; height: 20px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 10px; color: #fff; flex-shrink: 0; }
  58. .step-order { background: #ff6b35; }
  59. .step-item { background: #2196f3; }
  60. .step-delivery { background: #43e97b; }
  61. .step-coupon { background: #e91e63; }
  62. .calc-step .step-value { font-weight: 500; }
  63. .step-minus { color: #ff4500; }
  64. .step-plus { color: #333; }
  65. .calc-divider { border-top: 1px dashed #ddd; margin: 6px 0; }
  66. .calc-total { display: flex; justify-content: space-between; padding: 8px 0; font-size: 16px; font-weight: 700; }
  67. .calc-total .total-price { color: #ff4500; }
  68. /* Toggle switches */
  69. .toggle-section { padding: 12px 16px; background: #fafafa; border-top: 1px solid #f0f0f0; }
  70. .toggle-row { display: flex; align-items: center; justify-content: space-between; padding: 6px 0; font-size: 13px; }
  71. .toggle-row .toggle-info { display: flex; align-items: center; gap: 6px; }
  72. .toggle-row .toggle-info .dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
  73. .toggle { width: 44px; height: 24px; border-radius: 12px; background: #ddd; position: relative; cursor: pointer; transition: background 0.2s; flex-shrink: 0; }
  74. .toggle.active { background: #4facfe; }
  75. .toggle .knob { width: 20px; height: 20px; border-radius: 50%; background: #fff; position: absolute; top: 2px; left: 2px; transition: left 0.2s; box-shadow: 0 1px 3px rgba(0,0,0,0.2); }
  76. .toggle.active .knob { left: 22px; }
  77. /* Tabs */
  78. .tabs { display: flex; border-bottom: 1px solid #f0f0f0; }
  79. .tab { flex: 1; text-align: center; padding: 12px 0; font-size: 14px; color: #999; cursor: pointer; position: relative; transition: color 0.2s; }
  80. .tab.active { color: #ff6b35; font-weight: 600; }
  81. .tab.active::after { content: ''; position: absolute; bottom: 0; left: 30%; right: 30%; height: 3px; background: #ff6b35; border-radius: 2px; }
  82. .tab-content { display: none; }
  83. .tab-content.active { display: block; }
  84. /* Stack diagram */
  85. .stack-diagram { padding: 16px; }
  86. .stack-bar { display: flex; align-items: center; margin-bottom: 8px; }
  87. .stack-bar .bar-label { width: 80px; font-size: 11px; color: #666; text-align: right; padding-right: 10px; flex-shrink: 0; }
  88. .stack-bar .bar-track { flex: 1; height: 28px; background: #f5f5f5; border-radius: 6px; position: relative; overflow: hidden; }
  89. .stack-bar .bar-fill { height: 100%; border-radius: 6px; display: flex; align-items: center; justify-content: center; font-size: 11px; color: #fff; font-weight: 600; transition: width 0.5s ease; }
  90. .bar-original { background: linear-gradient(90deg, #b0b0b0, #999); }
  91. .bar-promo { background: linear-gradient(90deg, #ff6b35, #ff4500); }
  92. .bar-discount { background: linear-gradient(90deg, #4facfe, #2196f3); }
  93. .bar-delivery { background: linear-gradient(90deg, #43e97b, #38b249); }
  94. .bar-coupon { background: linear-gradient(90deg, #fa709a, #e91e63); }
  95. .bar-final { background: linear-gradient(90deg, #667eea, #764ba2); }
  96. .note { font-size: 11px; color: #999; padding: 0 16px 12px; line-height: 1.6; }
  97. /* Exclusive table */
  98. .mutex-table { padding: 12px 16px; }
  99. .mutex-table table { width: 100%; border-collapse: collapse; font-size: 11px; }
  100. .mutex-table th { background: #f8f8f8; padding: 6px 4px; text-align: center; border: 1px solid #eee; font-weight: 600; color: #333; }
  101. .mutex-table td { padding: 6px 4px; text-align: center; border: 1px solid #eee; }
  102. .mutex-yes { color: #43e97b; font-weight: 700; }
  103. .mutex-no { color: #ff4500; font-weight: 700; }
  104. .mutex-self { color: #ccc; }
  105. </style>
  106. </head>
  107. <body>
  108. <div class="page-title">美团商家促销类型解析</div>
  109. <!-- Tabs -->
  110. <div class="category">
  111. <div class="tabs">
  112. <div class="tab active" onclick="switchTab('overview')">类型总览</div>
  113. <div class="tab" onclick="switchTab('demo')">算价演示</div>
  114. <div class="tab" onclick="switchTab('mutex')">互斥规则</div>
  115. </div>
  116. <!-- Tab 1: Overview -->
  117. <div id="tab-overview" class="tab-content active">
  118. <!-- Order Level -->
  119. <div class="category cat-order">
  120. <div class="category-header">
  121. <div class="icon">📦</div>
  122. <div class="info">
  123. <h3>订单级促销</h3>
  124. <p>作用在"订单总价"上</p>
  125. </div>
  126. </div>
  127. <div class="promo-card">
  128. <div class="promo-title">满减活动 <span class="badge badge-auto">自动生效</span></div>
  129. <div class="promo-desc">订单金额达到X元自动减免Y元,可设多档位。全场商品参与,不需要选商品。</div>
  130. <div class="example">
  131. <div class="label">📋 示例</div>
  132. <div class="calc">
  133. 满减档位:满20减5 / 满40减12 / 满60减20<br>
  134. 订单商品合计 <span class="price">¥45</span> → 命中"满40减12"<br>
  135. 实付商品金额 = 45 - 12 = <span class="price">¥33</span>
  136. </div>
  137. </div>
  138. </div>
  139. <div class="promo-card">
  140. <div class="promo-title">门店新客立减 <span class="badge badge-auto">自动生效</span></div>
  141. <div class="promo-desc">首次在本店下单的用户,订单总价直接减X元。仅限新客。</div>
  142. <div class="example">
  143. <div class="label">📋 示例</div>
  144. <div class="calc">
  145. 新客立减 <span class="price">¥3</span><br>
  146. 新客下单 ¥45 → 实付 = 45 - 3 = <span class="price">¥42</span>
  147. </div>
  148. </div>
  149. </div>
  150. </div>
  151. <!-- Item Level -->
  152. <div class="category cat-item">
  153. <div class="category-header">
  154. <div class="icon">🏷️</div>
  155. <div class="info">
  156. <h3>商品级促销</h3>
  157. <p>作用在"指定商品单价"上</p>
  158. </div>
  159. </div>
  160. <div class="promo-card">
  161. <div class="promo-title">折扣商品 <span class="badge badge-select">选商品</span></div>
  162. <div class="promo-desc">商家选择特定商品设折扣价。只有被选中的商品打折,其他商品原价。自动创建"折扣"专区。</div>
  163. <div class="example">
  164. <div class="label">📋 示例</div>
  165. <div class="calc">
  166. 宫保鸡丁 原价 <span class="line-through">¥20</span> → 7折 = <span class="price">¥14</span><br>
  167. 麻婆豆腐 原价 ¥18(未设折扣,原价)<br>
  168. 订单合计 = 14 + 18 = <span class="price">¥32</span>
  169. </div>
  170. </div>
  171. </div>
  172. <div class="promo-card">
  173. <div class="promo-title">第二份半价 <span class="badge badge-select">选商品</span></div>
  174. <div class="promo-desc">选择特定商品,买2件时第2件半价。按商品单独计算。</div>
  175. <div class="example">
  176. <div class="label">📋 示例</div>
  177. <div class="calc">
  178. 可乐 原价 ¥6,买2件<br>
  179. = 6 + 6×0.5 = <span class="price">¥9</span>(省¥3)<br>
  180. 不是对订单总价打折,是这1件商品的价格变了
  181. </div>
  182. </div>
  183. </div>
  184. <div class="promo-card">
  185. <div class="promo-title">爆品特价 <span class="badge badge-select">选商品</span></div>
  186. <div class="promo-desc">选择特定商品设超低特价引流,可与满减/折扣同享(独特优势)。</div>
  187. <div class="example">
  188. <div class="label">📋 示例</div>
  189. <div class="calc">
  190. 招牌鸡腿饭 原价 <span class="line-through">¥25</span> → 爆品价 <span class="price">¥9.9</span><br>
  191. 爆品价 ¥9.9 仍然计入满减的订单金额
  192. </div>
  193. </div>
  194. </div>
  195. </div>
  196. <!-- Delivery Level -->
  197. <div class="category cat-delivery">
  198. <div class="category-header">
  199. <div class="icon">🛵</div>
  200. <div class="info">
  201. <h3>配送费级促销</h3>
  202. <p>作用在"配送费"上</p>
  203. </div>
  204. </div>
  205. <div class="promo-card">
  206. <div class="promo-title">减配送费 <span class="badge badge-auto">自动生效</span></div>
  207. <div class="promo-desc">商家固定补贴X元配送费,所有用户自动享受。</div>
  208. <div class="example">
  209. <div class="label">📋 示例</div>
  210. <div class="calc">
  211. 配送费 ¥5 → 商家补贴 ¥2 → 用户付 <span class="price">¥3</span><br>
  212. 与商品价格无关,只扣配送费
  213. </div>
  214. </div>
  215. </div>
  216. <div class="promo-card">
  217. <div class="promo-title">满减运费 <span class="badge badge-auto">自动生效</span></div>
  218. <div class="promo-desc">订单金额满X元免配送费。与"减配送费"互斥二选一。</div>
  219. <div class="example">
  220. <div class="label">📋 示例</div>
  221. <div class="calc">
  222. 满30元免配送费<br>
  223. 订单 ¥35 → 配送费 <span class="price">¥0</span><br>
  224. 订单 ¥25 → 配送费 ¥5(未达标)
  225. </div>
  226. </div>
  227. </div>
  228. </div>
  229. <!-- Coupon Level -->
  230. <div class="category cat-coupon">
  231. <div class="category-header">
  232. <div class="icon">🎫</div>
  233. <div class="info">
  234. <h3>优惠券类(商家券)</h3>
  235. <p>用户需先领券,下单时手动选择使用</p>
  236. </div>
  237. </div>
  238. <div class="promo-card">
  239. <div class="promo-title">满减券 <span class="badge badge-manual">用户选券</span></div>
  240. <div class="promo-desc">分"同享券"(可与满减叠加)和"互斥券"(不可与满减/折扣叠加)。作用在订单总价上。</div>
  241. <div class="example">
  242. <div class="label">📋 示例</div>
  243. <div class="calc">
  244. 满30减5元券(同享券)<br>
  245. 满减后 ¥33 → 再扣券 → <span class="price">¥28</span>
  246. </div>
  247. </div>
  248. </div>
  249. <div class="promo-card">
  250. <div class="promo-title">商品券 <span class="badge badge-manual">用户选券</span></div>
  251. <div class="promo-desc">只能用于指定商品。分"折扣券"(指定商品X折)和"抵用券"(指定商品免费兑换)。</div>
  252. <div class="example">
  253. <div class="label">📋 示例</div>
  254. <div class="calc">
  255. 抵用券:免费兑换1杯可乐(原价¥6)<br>
  256. 折扣券:宫保鸡丁5折券(¥20 → <span class="price">¥10</span>)
  257. </div>
  258. </div>
  259. </div>
  260. </div>
  261. </div>
  262. <!-- Tab 2: Demo -->
  263. <div id="tab-demo" class="tab-content">
  264. <div class="demo-section">
  265. <div class="demo-header">
  266. <h3>💰 算价演示</h3>
  267. <p>开启/关闭不同促销,看价格怎么变</p>
  268. </div>
  269. <div class="toggle-section">
  270. <div class="toggle-row">
  271. <div class="toggle-info">
  272. <div class="dot" style="background:#ff6b35"></div>
  273. <span>满减(满40减12)</span>
  274. </div>
  275. <div class="toggle active" onclick="toggle(this, 'manjian')"><div class="knob"></div></div>
  276. </div>
  277. <div class="toggle-row">
  278. <div class="toggle-info">
  279. <div class="dot" style="background:#2196f3"></div>
  280. <span>折扣(宫保鸡丁7折)</span>
  281. </div>
  282. <div class="toggle" onclick="toggle(this, 'zhekou')"><div class="knob"></div></div>
  283. </div>
  284. <div class="toggle-row">
  285. <div class="toggle-info">
  286. <div class="dot" style="background:#43e97b"></div>
  287. <span>减配送费(减¥2)</span>
  288. </div>
  289. <div class="toggle active" onclick="toggle(this, 'delivery')"><div class="knob"></div></div>
  290. </div>
  291. <div class="toggle-row">
  292. <div class="toggle-info">
  293. <div class="dot" style="background:#e91e63"></div>
  294. <span>商家满减券(满30减5)</span>
  295. </div>
  296. <div class="toggle active" onclick="toggle(this, 'coupon')"><div class="knob"></div></div>
  297. </div>
  298. </div>
  299. <div class="order-items">
  300. <div class="order-item">
  301. <span class="name">🍗 宫保鸡丁</span>
  302. <span class="item-price" id="item1-price">¥20</span>
  303. <span class="item-final" id="item1-final">¥20</span>
  304. <span class="item-tag item-tag-normal" id="item1-tag">原价</span>
  305. </div>
  306. <div class="order-item">
  307. <span class="name">🥘 麻婆豆腐</span>
  308. <span class="item-price">¥18</span>
  309. <span class="item-final">¥18</span>
  310. </div>
  311. <div class="order-item">
  312. <span class="name">🥤 可乐×2</span>
  313. <span class="item-price">¥12</span>
  314. <span class="item-final">¥12</span>
  315. </div>
  316. <div class="order-item">
  317. <span class="name">📦 餐盒费</span>
  318. <span class="item-price">¥3</span>
  319. <span class="item-final">¥3</span>
  320. </div>
  321. </div>
  322. <div class="calc-steps">
  323. <div class="calc-step">
  324. <span class="step-label"><span class="step-icon step-order">📦</span> 商品原价合计</span>
  325. <span class="step-value" id="step-original">¥53</span>
  326. </div>
  327. <div class="calc-step" id="row-zhekou">
  328. <span class="step-label"><span class="step-icon step-item">🏷️</span> 折扣(宫保鸡丁7折)</span>
  329. <span class="step-value step-minus" id="step-zhekou">—</span>
  330. </div>
  331. <div class="calc-step" id="row-discount-subtotal">
  332. <span class="step-label" style="color:#999; font-size:12px;">&nbsp;&nbsp;&nbsp;折扣后小计</span>
  333. <span class="step-value" id="step-discount-subtotal" style="color:#999; font-size:12px;">—</span>
  334. </div>
  335. <div class="calc-step" id="row-manjian">
  336. <span class="step-label"><span class="step-icon step-order">📦</span> 满减(满40减12)</span>
  337. <span class="step-value step-minus" id="step-manjian">-¥12</span>
  338. </div>
  339. <div class="calc-step" id="row-coupon">
  340. <span class="step-label"><span class="step-icon step-coupon">🎫</span> 商家满减券(满30减5)</span>
  341. <span class="step-value step-minus" id="step-coupon">-¥5</span>
  342. </div>
  343. <div class="calc-divider"></div>
  344. <div class="calc-step">
  345. <span class="step-label">商品实付</span>
  346. <span class="step-value" id="step-item-total">¥36</span>
  347. </div>
  348. <div class="calc-step" id="row-delivery">
  349. <span class="step-label"><span class="step-icon step-delivery">🛵</span> 配送费(原¥5,减¥2)</span>
  350. <span class="step-value step-plus" id="step-delivery">+¥3</span>
  351. </div>
  352. <div class="calc-divider"></div>
  353. <div class="calc-total">
  354. <span>实付金额</span>
  355. <span class="total-price" id="step-total">¥39</span>
  356. </div>
  357. </div>
  358. </div>
  359. <!-- Stack Diagram -->
  360. <div class="category">
  361. <div class="category-header">
  362. <div class="icon">📊</div>
  363. <div class="info">
  364. <h3>价格叠加图</h3>
  365. <p>各层级优惠怎么从原价扣到实付</p>
  366. </div>
  367. </div>
  368. <div class="stack-diagram">
  369. <div class="stack-bar">
  370. <span class="bar-label">商品原价</span>
  371. <div class="bar-track"><div class="bar-fill bar-original" id="bar-original" style="width:100%">¥53</div></div>
  372. </div>
  373. <div class="stack-bar" id="bar-zhekou-row">
  374. <span class="bar-label">商品折扣</span>
  375. <div class="bar-track"><div class="bar-fill bar-discount" id="bar-zhekou" style="width:0%"></div></div>
  376. </div>
  377. <div class="stack-bar" id="bar-manjian-row">
  378. <span class="bar-label">订单满减</span>
  379. <div class="bar-track"><div class="bar-fill bar-promo" id="bar-manjian" style="width:22%">-¥12</div></div>
  380. </div>
  381. <div class="stack-bar" id="bar-coupon-row">
  382. <span class="bar-label">商家券</span>
  383. <div class="bar-track"><div class="bar-fill bar-coupon" id="bar-coupon" style="width:9%">-¥5</div></div>
  384. </div>
  385. <div class="stack-bar" id="bar-delivery-row">
  386. <span class="bar-label">配送费</span>
  387. <div class="bar-track"><div class="bar-fill bar-delivery" id="bar-delivery" style="width:5%">+¥3</div></div>
  388. </div>
  389. <div class="stack-bar">
  390. <span class="bar-label" style="font-weight:700;">实付</span>
  391. <div class="bar-track"><div class="bar-fill bar-final" id="bar-final" style="width:73%">¥39</div></div>
  392. </div>
  393. </div>
  394. <div class="note">
  395. 💡 每一层作用在不同的价格基础上:商品折扣改单价 → 满减看折后订单总额 → 券再扣 → 配送费单独加
  396. </div>
  397. </div>
  398. </div>
  399. <!-- Tab 3: Mutex -->
  400. <div id="tab-mutex" class="tab-content">
  401. <div class="category">
  402. <div class="category-header">
  403. <div class="icon">⚠️</div>
  404. <div class="info">
  405. <h3>互斥规则</h3>
  406. <p>哪些促销不能同时使用</p>
  407. </div>
  408. </div>
  409. <div class="mutex-table">
  410. <table>
  411. <tr>
  412. <th></th>
  413. <th>满减</th>
  414. <th>折扣</th>
  415. <th>第二份<br>半价</th>
  416. <th>新客<br>立减</th>
  417. <th>减配<br>送费</th>
  418. <th>满减<br>运费</th>
  419. </tr>
  420. <tr>
  421. <th>满减</th>
  422. <td class="mutex-self">—</td>
  423. <td class="mutex-no">✗</td>
  424. <td class="mutex-no">✗</td>
  425. <td class="mutex-yes">✓</td>
  426. <td class="mutex-yes">✓</td>
  427. <td class="mutex-yes">✓</td>
  428. </tr>
  429. <tr>
  430. <th>折扣</th>
  431. <td class="mutex-no">✗</td>
  432. <td class="mutex-self">—</td>
  433. <td class="mutex-no">✗</td>
  434. <td class="mutex-yes">✓</td>
  435. <td class="mutex-yes">✓</td>
  436. <td class="mutex-yes">✓</td>
  437. </tr>
  438. <tr>
  439. <th>第二份半价</th>
  440. <td class="mutex-no">✗</td>
  441. <td class="mutex-no">✗</td>
  442. <td class="mutex-self">—</td>
  443. <td class="mutex-no">✗</td>
  444. <td class="mutex-yes">✓</td>
  445. <td class="mutex-yes">✓</td>
  446. </tr>
  447. <tr>
  448. <th>新客立减</th>
  449. <td class="mutex-yes">✓</td>
  450. <td class="mutex-yes">✓</td>
  451. <td class="mutex-no">✗</td>
  452. <td class="mutex-self">—</td>
  453. <td class="mutex-yes">✓</td>
  454. <td class="mutex-yes">✓</td>
  455. </tr>
  456. <tr>
  457. <th>减配送费</th>
  458. <td class="mutex-yes">✓</td>
  459. <td class="mutex-yes">✓</td>
  460. <td class="mutex-yes">✓</td>
  461. <td class="mutex-yes">✓</td>
  462. <td class="mutex-self">—</td>
  463. <td class="mutex-no">✗</td>
  464. </tr>
  465. <tr>
  466. <th>满减运费</th>
  467. <td class="mutex-yes">✓</td>
  468. <td class="mutex-yes">✓</td>
  469. <td class="mutex-yes">✓</td>
  470. <td class="mutex-yes">✓</td>
  471. <td class="mutex-no">✗</td>
  472. <td class="mutex-self">—</td>
  473. </tr>
  474. </table>
  475. </div>
  476. <div class="note">
  477. ✓ = 可同时使用 &nbsp;&nbsp; ✗ = 互斥不可同时使用<br><br>
  478. 💡 核心互斥链:满减 ↔ 折扣 ↔ 第二份半价(三选一)<br>
  479. 💡 配送费互斥:减配送费 ↔ 满减运费(二选一)<br>
  480. 💡 满赠、售卖代金券、下单返券与所有活动同享
  481. </div>
  482. </div>
  483. </div>
  484. </div>
  485. <script>
  486. // State
  487. const state = {
  488. manjian: true,
  489. zhekou: false,
  490. delivery: true,
  491. coupon: true
  492. };
  493. // Prices
  494. const ORIGINAL_PRICE = { chicken: 20, tofu: 18, cola: 12, box: 3 }; // cola = 6*2
  495. const DELIVERY_FEE = 5;
  496. const MANJIAN_THRESHOLD = 40;
  497. const MANJIAN_AMOUNT = 12;
  498. const ZHEKOU_RATE = 0.7;
  499. const DELIVERY_DISCOUNT = 2;
  500. const COUPON_THRESHOLD = 30;
  501. const COUPON_AMOUNT = 5;
  502. function toggle(el, key) {
  503. // 满减和折扣互斥
  504. if (key === 'manjian' && !state.manjian) {
  505. state.zhekou = false;
  506. document.querySelectorAll('.toggle')[1].classList.remove('active');
  507. }
  508. if (key === 'zhekou' && !state.zhekou) {
  509. state.manjian = false;
  510. document.querySelectorAll('.toggle')[0].classList.remove('active');
  511. }
  512. state[key] = !state[key];
  513. el.classList.toggle('active');
  514. recalculate();
  515. }
  516. function recalculate() {
  517. let chicken = ORIGINAL_PRICE.chicken;
  518. let itemDiscount = 0;
  519. // 折扣
  520. if (state.zhekou) {
  521. chicken = Math.round(ORIGINAL_PRICE.chicken * ZHEKOU_RATE * 10) / 10;
  522. itemDiscount = ORIGINAL_PRICE.chicken - chicken;
  523. document.getElementById('item1-final').textContent = '¥' + chicken;
  524. document.getElementById('item1-tag').textContent = '7折';
  525. document.getElementById('item1-tag').className = 'item-tag item-tag-discount';
  526. } else {
  527. document.getElementById('item1-final').textContent = '¥' + ORIGINAL_PRICE.chicken;
  528. document.getElementById('item1-tag').textContent = '原价';
  529. document.getElementById('item1-tag').className = 'item-tag item-tag-normal';
  530. }
  531. let subtotal = chicken + ORIGINAL_PRICE.tofu + ORIGINAL_PRICE.cola + ORIGINAL_PRICE.box;
  532. // 满减
  533. let manjianAmount = 0;
  534. if (state.manjian && subtotal >= MANJIAN_THRESHOLD) {
  535. manjianAmount = MANJIAN_AMOUNT;
  536. }
  537. // 券
  538. let couponAmount = 0;
  539. let afterManjian = subtotal - manjianAmount;
  540. if (state.coupon && afterManjian >= COUPON_THRESHOLD) {
  541. couponAmount = COUPON_AMOUNT;
  542. }
  543. let itemTotal = subtotal - manjianAmount - couponAmount;
  544. // 配送费
  545. let deliveryPay = DELIVERY_FEE;
  546. if (state.delivery) {
  547. deliveryPay = DELIVERY_FEE - DELIVERY_DISCOUNT;
  548. }
  549. let total = itemTotal + deliveryPay;
  550. // Update UI
  551. document.getElementById('step-original').textContent = '¥' + ORIGINAL_PRICE.chicken;
  552. if (state.zhekou) {
  553. document.getElementById('row-zhekou').style.display = 'flex';
  554. document.getElementById('row-discount-subtotal').style.display = 'flex';
  555. document.getElementById('step-zhekou').textContent = '-¥' + itemDiscount.toFixed(1);
  556. document.getElementById('step-discount-subtotal').textContent = '¥' + subtotal;
  557. document.getElementById('step-original').textContent = '¥' + (ORIGINAL_PRICE.chicken + ORIGINAL_PRICE.tofu + ORIGINAL_PRICE.cola + ORIGINAL_PRICE.box);
  558. } else {
  559. document.getElementById('row-zhekou').style.display = 'none';
  560. document.getElementById('row-discount-subtotal').style.display = 'none';
  561. }
  562. if (state.manjian && manjianAmount > 0) {
  563. document.getElementById('row-manjian').style.display = 'flex';
  564. document.getElementById('step-manjian').textContent = '-¥' + manjianAmount;
  565. } else {
  566. document.getElementById('row-manjian').style.display = state.manjian ? 'flex' : 'none';
  567. document.getElementById('step-manjian').textContent = state.manjian ? '未达到¥' + MANJIAN_THRESHOLD : '';
  568. document.getElementById('step-manjian').style.color = state.manjian && manjianAmount === 0 ? '#999' : '#ff4500';
  569. }
  570. if (state.coupon) {
  571. document.getElementById('row-coupon').style.display = 'flex';
  572. document.getElementById('step-coupon').textContent = couponAmount > 0 ? '-¥' + couponAmount : '未达到¥' + COUPON_THRESHOLD;
  573. document.getElementById('step-coupon').style.color = couponAmount > 0 ? '#ff4500' : '#999';
  574. } else {
  575. document.getElementById('row-coupon').style.display = 'none';
  576. }
  577. document.getElementById('step-item-total').textContent = '¥' + itemTotal;
  578. if (state.delivery) {
  579. document.getElementById('row-delivery').style.display = 'flex';
  580. document.getElementById('step-delivery').textContent = '+¥' + deliveryPay + '(原¥' + DELIVERY_FEE + ')';
  581. } else {
  582. document.getElementById('row-delivery').style.display = 'flex';
  583. document.getElementById('step-delivery').textContent = '+¥' + DELIVERY_FEE;
  584. }
  585. document.getElementById('step-total').textContent = '¥' + total;
  586. // Update bars
  587. let maxVal = ORIGINAL_PRICE.chicken + ORIGINAL_PRICE.tofu + ORIGINAL_PRICE.cola + ORIGINAL_PRICE.box + DELIVERY_FEE;
  588. document.getElementById('bar-original').style.width = ((subtotal + itemDiscount) / maxVal * 100) + '%';
  589. document.getElementById('bar-original').textContent = '¥' + (subtotal + itemDiscount);
  590. if (state.zhekou) {
  591. document.getElementById('bar-zhekou-row').style.display = 'flex';
  592. document.getElementById('bar-zhekou').style.width = (itemDiscount / maxVal * 100) + '%';
  593. document.getElementById('bar-zhekou').textContent = '-¥' + itemDiscount.toFixed(1);
  594. } else {
  595. document.getElementById('bar-zhekou-row').style.display = 'none';
  596. }
  597. if (state.manjian && manjianAmount > 0) {
  598. document.getElementById('bar-manjian-row').style.display = 'flex';
  599. document.getElementById('bar-manjian').style.width = (manjianAmount / maxVal * 100) + '%';
  600. document.getElementById('bar-manjian').textContent = '-¥' + manjianAmount;
  601. } else {
  602. document.getElementById('bar-manjian-row').style.display = 'none';
  603. }
  604. if (state.coupon && couponAmount > 0) {
  605. document.getElementById('bar-coupon-row').style.display = 'flex';
  606. document.getElementById('bar-coupon').style.width = (couponAmount / maxVal * 100) + '%';
  607. document.getElementById('bar-coupon').textContent = '-¥' + couponAmount;
  608. } else {
  609. document.getElementById('bar-coupon-row').style.display = 'none';
  610. }
  611. document.getElementById('bar-delivery').style.width = (deliveryPay / maxVal * 100) + '%';
  612. document.getElementById('bar-delivery').textContent = '+¥' + deliveryPay;
  613. document.getElementById('bar-final').style.width = (total / maxVal * 100) + '%';
  614. document.getElementById('bar-final').textContent = '¥' + total;
  615. }
  616. function switchTab(name) {
  617. document.querySelectorAll('.tab').forEach((t, i) => {
  618. t.classList.toggle('active', ['overview', 'demo', 'mutex'][i] === name);
  619. });
  620. document.querySelectorAll('.tab-content').forEach(tc => tc.classList.remove('active'));
  621. document.getElementById('tab-' + name).classList.add('active');
  622. }
  623. // Init
  624. recalculate();
  625. </script>
  626. </body>
  627. </html>