小草面馆自助点餐_H5/gen.py · 约 55032 字符
1#!/usr/bin/env python32# -*- coding: utf-8 -*-3"""生成小草面馆自助点餐 H5 项目所有文件(8页:index/category/detail/cart/order/orders/member/mine)"""4import os5import re67OUT = os.path.dirname(os.path.abspath(__file__))89CSS = """/* 小草面馆自助点餐 · 移动端 H5 样式 */10*{margin:0;padding:0;box-sizing:border-box}11body{font-family:-apple-system,"PingFang SC","Microsoft YaHei",sans-serif;background:#fdf6ec;color:#523521;max-width:430px;margin:0 auto;min-height:100vh}12a{text-decoration:none;color:inherit}13ul{list-style:none}14:root{--primary:#c2410c;--primary-dark:#9a3412;--primary-light:#fde4d6;--secondary:#ea580c;--accent:#f59e0b;--dark:#7c2d12;--gray:#9c8b7c;--light-gray:#f6ebdd;--green:#16a34a;--blue:#2563eb;--orange:#ea580c;--red:#dc2626}15.header{background:linear-gradient(135deg,#9a3412,#c2410c);color:#fff;padding:12px 16px;display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:100;box-shadow:0 2px 8px rgba(154,52,18,.3)}16.header .back{font-size:22px;cursor:pointer;width:32px}17.header h1{font-size:17px;font-weight:600;flex:1;text-align:center}18.header .right{width:32px;text-align:right;font-size:14px}19.tabbar{position:fixed;bottom:0;left:50%;transform:translateX(-50%);width:100%;max-width:430px;background:#fff;border-top:1px solid #eee;display:flex;z-index:100;padding-bottom:env(safe-area-inset-bottom)}20.tabbar a{flex:1;text-align:center;padding:8px 0;color:#999;font-size:11px}21.tabbar a.active{color:var(--primary)}22.tabbar a .icon{font-size:22px;display:block;margin-bottom:2px}23.card{background:#fff;border-radius:12px;margin:12px;padding:16px;box-shadow:0 1px 4px rgba(0,0,0,.05)}24.section-title{font-size:16px;font-weight:700;margin:16px 16px 8px;display:flex;justify-content:space-between;align-items:center}25.section-title span{font-size:12px;color:#999;font-weight:400}26.btn{display:block;width:100%;padding:13px;border:none;border-radius:25px;font-size:15px;font-weight:600;cursor:pointer;text-align:center}27.btn-primary{background:linear-gradient(135deg,#9a3412,#c2410c);color:#fff}28.btn-gold{background:linear-gradient(135deg,#d97706,#f59e0b);color:#fff}29.btn-outline{background:#fff;border:1px solid var(--primary);color:var(--primary)}30.btn-red{background:linear-gradient(135deg,#dc2626,#ea580c);color:#fff}31.badge{display:inline-block;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:600}32.badge-hot{background:#fff1f0;color:#dc2626}33.badge-new{background:#eef2ff;color:var(--blue)}34.badge-sale{background:#fff7e6;color:var(--orange)}35.badge-gold{background:#fdf6e3;color:var(--accent)}36.tag{display:inline-block;padding:2px 6px;border-radius:4px;font-size:11px;background:var(--light-gray);color:#a4693b;margin:2px 4px 0 0}37/* 首页 */38.banner{height:160px;margin:12px;border-radius:14px;background:linear-gradient(135deg,#9a3412,#c2410c,#f59e0b);color:#fff;display:flex;align-items:center;padding:20px;position:relative;overflow:hidden}39.banner .bn-title{font-size:22px;font-weight:800;letter-spacing:1px}40.banner .bn-sub{font-size:12px;opacity:.94;margin-top:6px;line-height:1.7}41.banner .bn-badge{display:inline-block;background:rgba(255,255,255,.22);padding:4px 12px;border-radius:14px;font-size:11px;margin-top:10px}42.banner .bn-emoji{position:absolute;right:12px;font-size:66px;opacity:.95}43.table-box{background:#fff;border-radius:14px;margin:12px;padding:14px;display:flex;align-items:center;gap:12px;box-shadow:0 1px 4px rgba(0,0,0,.05)}44.table-box .tb-ico{font-size:30px}45.table-box .tb-body{flex:1}46.table-box .tb-body b{font-size:14px}47.table-box .tb-body span{font-size:11px;color:#9c8b7c;display:block;margin-top:2px}48.table-box .tb-btn{background:linear-gradient(135deg,#9a3412,#c2410c);color:#fff;padding:8px 16px;border-radius:16px;font-size:12px;font-weight:700;white-space:nowrap}49.seckill{background:#fff;border-radius:14px;margin:12px;overflow:hidden;box-shadow:0 1px 4px rgba(0,0,0,.05)}50.seckill .sk-head{background:linear-gradient(135deg,#dc2626,#ea580c);color:#fff;padding:10px 14px;display:flex;align-items:center;gap:10px}51.seckill .sk-head b{font-size:15px}52.seckill .sk-head .sk-time{display:flex;gap:3px;margin-left:auto}53.seckill .sk-head .sk-time i{background:rgba(255,255,255,.25);padding:2px 6px;border-radius:4px;font-size:13px;font-style:normal;font-weight:700}54.seckill .sk-body{display:flex;gap:10px;padding:12px;overflow-x:auto;scrollbar-width:none}55.seckill .sk-item{width:96px;flex-shrink:0;text-align:center}56.seckill .sk-item .sk-img{height:72px;border-radius:10px;background:var(--primary-light);display:flex;align-items:center;justify-content:center;font-size:36px}57.seckill .sk-item .sk-name{font-size:11px;margin-top:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}58.seckill .sk-item .sk-price{color:var(--red);font-weight:800;font-size:14px;margin-top:2px}59.seckill .sk-item .sk-old{color:#c4b5a5;font-size:10px;text-decoration:line-through}60.quick-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;padding:16px 10px;background:#fff;margin:12px;border-radius:14px}61.quick-grid a{text-align:center;font-size:11px;color:#a4693b}62.quick-grid a .qicon{width:44px;height:44px;margin:0 auto 5px;border-radius:50%;background:var(--primary-light);display:flex;align-items:center;justify-content:center;font-size:22px}63.coupon-card{background:linear-gradient(135deg,#9a3412,#c2410c);margin:12px;border-radius:14px;padding:14px;display:flex;align-items:center;gap:12px;color:#fff}64.coupon-card .cc-left{flex:1}65.coupon-card .cc-left b{font-size:18px;display:block}66.coupon-card .cc-left span{font-size:11px;opacity:.9}67.coupon-card .cc-btn{background:#fff;color:#c2410c;padding:8px 16px;border-radius:16px;font-size:12px;font-weight:700;white-space:nowrap}68.noodle-card{background:#fff;border-radius:14px;margin:10px 12px;padding:12px;display:flex;gap:12px;box-shadow:0 1px 4px rgba(0,0,0,.05)}69.noodle-card .nc-img{width:92px;height:92px;border-radius:10px;background:linear-gradient(135deg,#fde4d6,#fbdcc6);display:flex;align-items:center;justify-content:center;font-size:44px;flex-shrink:0}70.noodle-card .nc-body{flex:1;min-width:0}71.noodle-card .nc-name{font-size:14px;font-weight:700}72.noodle-card .nc-desc{font-size:11px;color:#9c8b7c;margin-top:3px}73.noodle-card .nc-meta{font-size:10px;color:#b5a697;margin-top:3px}74.noodle-card .nc-foot{display:flex;justify-content:space-between;align-items:center;margin-top:6px}75.noodle-card .nc-price{color:var(--red);font-weight:800;font-size:17px}76.noodle-card .nc-price small{font-size:11px;color:#9c8b7c;font-weight:400}77.noodle-card .nc-add{background:linear-gradient(135deg,#9a3412,#c2410c);color:#fff;width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:17px;font-weight:700}78/* 菜单分类 */79.cat-tabs{display:flex;gap:8px;padding:0 12px;overflow-x:auto;padding-bottom:4px;scrollbar-width:none;position:sticky;top:0;z-index:99;background:#fdf6ec}80.cat-tab{padding:8px 14px;border:1px solid #efd9c4;border-radius:20px;font-size:12px;cursor:pointer;background:#fff;white-space:nowrap;flex-shrink:0}81.cat-tab.sel{border-color:var(--primary);background:var(--primary-light);color:var(--primary-dark);font-weight:600}82.sort-bar{display:flex;gap:14px;padding:10px 12px;font-size:13px;color:#a4693b}83.sort-bar span.on{color:var(--primary);font-weight:700}84.cart-float{position:fixed;bottom:0;left:50%;transform:translateX(-50%);width:100%;max-width:430px;background:#fff;border-top:1px solid #eee;display:flex;align-items:center;padding:10px 12px;padding-bottom:calc(10px + env(safe-area-inset-bottom));z-index:100;gap:10px;box-shadow:0 -2px 8px rgba(0,0,0,.06)}85.cart-float .cf-cart{display:flex;align-items:center;gap:6px;font-size:12px;color:#a4693b}86.cart-float .cf-cart .ico{font-size:24px;position:relative}87.cart-float .cf-cart .num{position:absolute;top:-6px;right:-10px;background:var(--red);color:#fff;border-radius:9px;font-size:9px;padding:1px 5px}88.cart-float .cf-total{flex:1;text-align:right;font-size:12px;color:#9c8b7c}89.cart-float .cf-total b{color:var(--red);font-size:18px}90.cart-float .cf-btn{background:linear-gradient(135deg,#9a3412,#c2410c);color:#fff;border-radius:20px;padding:11px 22px;font-size:14px;font-weight:600}91/* 详情 */92.detail-img{height:230px;background:linear-gradient(135deg,#fde4d6,#fbdcc6);display:flex;align-items:center;justify-content:center;font-size:84px;position:relative}93.detail-img .di-badge{position:absolute;top:12px;left:12px;background:rgba(0,0,0,.45);color:#fff;padding:4px 10px;border-radius:12px;font-size:11px}94.detail-price{background:#fff;margin:12px;border-radius:14px;padding:16px}95.detail-price .dp-num{font-size:26px;font-weight:800;color:var(--red)}96.detail-price .dp-num small{font-size:12px;color:#999}97.detail-price .dp-meta{font-size:12px;color:#9c8b7c;margin-top:4px;line-height:1.7}98.detail-price .dp-row{display:flex;gap:8px;margin-top:10px}99.detail-price .dp-cell{flex:1;background:var(--light-gray);border-radius:10px;padding:8px;text-align:center;font-size:11px;color:#a4693b}100.spec-box{background:#fff;margin:12px;border-radius:14px;padding:16px}101.spec-box .sb-title{font-size:14px;font-weight:700;margin-bottom:10px}102.spec-row{display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:1px solid #f6ebdd}103.spec-row:last-child{border-bottom:none}104.spec-row .sr-label{width:70px;font-size:13px;color:#a4693b;flex-shrink:0}105.spec-row .sr-opts{display:flex;gap:8px;flex:1;flex-wrap:wrap}106.spec-opt{padding:6px 12px;border:1px solid #efd9c4;border-radius:14px;font-size:12px;cursor:pointer;background:#fff}107.spec-opt.sel{border-color:var(--primary);background:var(--primary-light);color:var(--primary-dark);font-weight:600}108.spec-row .sr-num{display:flex;align-items:center;gap:8px;margin-left:auto}109.spec-row .sr-num i{width:26px;height:26px;border:1px solid #efd9c4;border-radius:50%;display:flex;align-items:center;justify-content:center;font-style:normal;cursor:pointer}110.eval-card{background:#fff;border-radius:14px;margin:10px 12px;padding:12px;box-shadow:0 1px 4px rgba(0,0,0,.05)}111.eval-card .ev-head{display:flex;align-items:center;gap:8px;font-size:12px}112.eval-card .ev-avatar{width:28px;height:28px;border-radius:50%;background:var(--primary-light);display:flex;align-items:center;justify-content:center;font-size:14px}113.eval-card .ev-star{color:var(--accent);font-size:11px}114.eval-card .ev-text{font-size:12px;color:#6b4a30;line-height:1.7;margin-top:6px}115.buy-bar{position:fixed;bottom:0;left:50%;transform:translateX(-50%);width:100%;max-width:430px;background:#fff;border-top:1px solid #eee;display:flex;align-items:center;padding:10px 12px;padding-bottom:calc(10px + env(safe-area-inset-bottom));z-index:100;gap:10px}116.buy-bar .bb-cart{display:flex;align-items:center;gap:6px;font-size:12px;color:#a4693b}117.buy-bar .bb-cart .ico{font-size:24px;position:relative}118.buy-bar .bb-cart .num{position:absolute;top:-6px;right:-10px;background:var(--red);color:#fff;border-radius:9px;font-size:9px;padding:1px 5px}119.buy-bar .bb-btn{flex:1;border-radius:20px;padding:11px;text-align:center;color:#fff;font-size:14px;font-weight:600}120.buy-bar .bb-btn.buy{background:linear-gradient(135deg,#d97706,#f59e0b)}121.buy-bar .bb-btn.now{background:linear-gradient(135deg,#9a3412,#c2410c)}122/* 购物车 */123.cart-item{background:#fff;border-radius:14px;margin:10px 12px;padding:12px;display:flex;gap:12px;align-items:center;box-shadow:0 1px 4px rgba(0,0,0,.05)}124.cart-item .ci-check{width:22px;height:22px;border-radius:50%;border:2px solid #e0c9b4;flex-shrink:0;display:flex;align-items:center;justify-content:center;color:#fff;font-size:12px}125.cart-item.checked .ci-check{background:var(--primary);border-color:var(--primary)}126.cart-item .ci-img{width:70px;height:70px;border-radius:10px;background:var(--primary-light);display:flex;align-items:center;justify-content:center;font-size:32px;flex-shrink:0}127.cart-item .ci-body{flex:1;min-width:0}128.cart-item .ci-name{font-size:13px;font-weight:700}129.cart-item .ci-spec{font-size:11px;color:#9c8b7c;margin-top:2px}130.cart-item .ci-foot{display:flex;justify-content:space-between;align-items:center;margin-top:6px}131.cart-item .ci-price{color:var(--red);font-weight:800}132.cart-item .ci-num{display:flex;align-items:center;gap:8px}133.cart-item .ci-num i{width:24px;height:24px;border:1px solid #efd9c4;border-radius:50%;display:flex;align-items:center;justify-content:center;font-style:normal;font-size:13px}134.settle-bar{position:fixed;bottom:0;left:50%;transform:translateX(-50%);width:100%;max-width:430px;background:#fff;border-top:1px solid #eee;display:flex;align-items:center;padding:10px 12px;padding-bottom:calc(10px + env(safe-area-inset-bottom));z-index:100;gap:10px}135.settle-bar .sb-all{display:flex;align-items:center;gap:6px;font-size:12px;color:#a4693b}136.settle-bar .sb-total{flex:1;text-align:right;font-size:12px;color:#9c8b7c}137.settle-bar .sb-total b{color:var(--red);font-size:18px}138.settle-bar .sb-btn{background:linear-gradient(135deg,#9a3412,#c2410c);color:#fff;border-radius:20px;padding:11px 26px;font-size:14px;font-weight:600}139.check-box{background:#fff;border-radius:14px;margin:12px;padding:16px}140.check-box .cb-row{display:flex;align-items:center;gap:10px;padding:10px 0;border-bottom:1px solid #f6ebdd;font-size:13px}141.check-box .cb-row:last-child{border-bottom:none}142.check-box .cb-label{width:86px;color:#a4693b;flex-shrink:0}143.check-box .cb-val{flex:1;text-align:right;color:#523521}144.check-box .cb-val.dim{color:#b5a697}145.check-box .cb-val .opt{padding:5px 10px;border:1px solid #efd9c4;border-radius:12px;font-size:12px;margin-left:6px}146.check-box .cb-val .opt.sel{border-color:var(--primary);background:var(--primary-light);color:var(--primary-dark)}147/* 提交订单 */148.pay-card{background:#fff;border-radius:14px;margin:12px;padding:16px}149.pay-card .pc-row{display:flex;align-items:center;gap:10px;padding:11px 0;border-bottom:1px solid #f6ebdd;font-size:13px}150.pay-card .pc-row:last-child{border-bottom:none}151.pay-card .pc-label{width:72px;color:#a4693b;flex-shrink:0}152.pay-card .pc-val{flex:1;color:#523521}153.pay-card .pc-val.dim{color:#b5a697}154.pay-way{background:#fff;border-radius:14px;margin:12px;padding:16px}155.pay-way .pw-title{font-size:14px;font-weight:700;margin-bottom:8px}156.pay-way .pw-item{display:flex;align-items:center;gap:10px;padding:12px 0;border-bottom:1px solid #f6ebdd;font-size:14px}157.pay-way .pw-item:last-child{border-bottom:none}158.pay-way .pw-ico{font-size:24px}159.pay-way .pw-radio{margin-left:auto;width:20px;height:20px;border-radius:50%;border:2px solid #e0c9b4;display:flex;align-items:center;justify-content:center;color:#fff;font-size:11px}160.pay-way .pw-item.sel .pw-radio{background:var(--primary);border-color:var(--primary)}161/* 订单状态 */162.order-tabs{display:flex;background:#fff;border-bottom:1px solid #f6ebdd;position:sticky;top:0;z-index:99}163.order-tabs a{flex:1;text-align:center;padding:12px 4px;font-size:13px;color:#a4693b;position:relative}164.order-tabs a.active{color:var(--primary);font-weight:700}165.order-tabs a.active::after{content:"";position:absolute;bottom:0;left:25%;width:50%;height:3px;background:var(--primary);border-radius:3px}166.order-card{background:#fff;border-radius:14px;margin:10px 12px;padding:14px;box-shadow:0 1px 4px rgba(0,0,0,.05)}167.order-card .oc-head{display:flex;justify-content:space-between;font-size:12px;color:#9c8b7c;padding-bottom:10px;border-bottom:1px solid #f6ebdd}168.order-card .oc-head .st{color:var(--primary);font-weight:700}169.order-card .oc-goods{display:flex;gap:10px;padding:10px 0;align-items:center}170.order-card .oc-goods .og-img{width:52px;height:52px;border-radius:8px;background:var(--primary-light);display:flex;align-items:center;justify-content:center;font-size:24px}171.order-card .oc-goods .og-name{font-size:13px;font-weight:600;flex:1}172.order-card .oc-goods .og-price{font-size:12px;color:#9c8b7c}173.order-card .oc-foot{display:flex;justify-content:space-between;align-items:center;font-size:12px;color:#9c8b7c}174.order-card .oc-foot b{color:var(--red);font-size:15px}175.order-card .oc-ops{display:flex;gap:8px;margin-top:10px;justify-content:flex-end}176.order-card .oc-ops i{padding:6px 14px;border:1px solid #efd9c4;border-radius:15px;font-style:normal;font-size:12px}177.order-card .oc-ops i.main{background:linear-gradient(135deg,#9a3412,#c2410c);color:#fff;border-color:transparent}178.call-bar{display:flex;gap:8px;margin:10px 12px}179.call-bar i{flex:1;text-align:center;padding:9px 0;border:1px solid #efd9c4;border-radius:14px;font-style:normal;font-size:12px;color:#a4693b}180.call-bar i.main{background:var(--primary-light);color:var(--primary-dark);border-color:var(--primary);font-weight:600}181.status-line{background:#fff;border-radius:14px;margin:12px;padding:16px}182.status-line .sl-dot{display:flex;gap:12px;position:relative;padding-bottom:16px}183.status-line .sl-dot:last-child{padding-bottom:0}184.status-line .sl-c{width:14px;height:14px;border-radius:50%;background:#e8d5c2;flex-shrink:0;margin-top:2px;position:relative;z-index:1}185.status-line .sl-dot.done .sl-c{background:var(--green)}186.status-line .sl-dot.now .sl-c{background:var(--accent);box-shadow:0 0 0 4px #fdf0d5}187.status-line .sl-dot::before{content:"";position:absolute;left:6px;top:16px;bottom:-2px;width:2px;background:#f0e2d2}188.status-line .sl-dot:last-child::before{display:none}189.status-line .sl-title{font-size:13px;font-weight:600}190.status-line .sl-time{font-size:11px;color:#9c8b7c;margin-top:2px}191/* 会员 */192.vip-card{background:linear-gradient(135deg,#9a3412,#c2410c,#f59e0b);margin:12px;border-radius:16px;color:#fff;padding:20px;position:relative;overflow:hidden}193.vip-card::after{content:"VIP";position:absolute;right:12px;top:10px;font-size:40px;font-weight:800;opacity:.15}194.vip-card .vc-level{font-size:13px;opacity:.9}195.vip-card .vc-name{font-size:20px;font-weight:800;margin-top:2px}196.vip-card .vc-exp{font-size:11px;opacity:.85;margin-top:4px}197.vip-card .vc-bar{height:6px;background:rgba(255,255,255,.25);border-radius:3px;margin-top:14px;position:relative}198.vip-card .vc-bar i{display:block;height:100%;width:68%;background:linear-gradient(90deg,#f59e0b,#facc15);border-radius:3px}199.assets{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;padding:0 12px}200.asset-item{background:#fff;border-radius:12px;text-align:center;padding:14px 4px;box-shadow:0 1px 4px rgba(0,0,0,.05)}201.asset-item b{display:block;font-size:19px;color:var(--primary-dark)}202.asset-item span{font-size:11px;color:#9c8b7c}203.sign-btn{background:linear-gradient(135deg,#d97706,#f59e0b);color:#fff;border-radius:20px;padding:11px;text-align:center;font-size:14px;font-weight:700;margin:12px;cursor:pointer}204.sign-btn.done{background:#e8d5c2;color:#9c8b7c}205.vip-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;padding:0 12px}206.vip-item{background:#fff;border-radius:12px;padding:14px;box-shadow:0 1px 4px rgba(0,0,0,.05)}207.vip-item .vi-emoji{font-size:26px}208.vip-item .vi-name{font-size:13px;font-weight:700;margin-top:4px}209.vip-item .vi-desc{font-size:10px;color:#9c8b7c;margin-top:2px;line-height:1.5}210.recharge-box{background:#fff;border-radius:14px;margin:12px;padding:16px}211.recharge-box .rb-title{font-size:14px;font-weight:700;margin-bottom:10px}212.recharge-opts{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}213.recharge-opt{border:1px solid #efd9c4;border-radius:10px;text-align:center;padding:10px 4px;font-size:12px}214.recharge-opt.sel{border-color:var(--primary);background:var(--primary-light);color:var(--primary-dark)}215.recharge-opt b{display:block;font-size:14px}216.recharge-opt span{color:#b5a697;font-size:10px}217/* 我的 */218.user-card{background:linear-gradient(135deg,#9a3412,#c2410c);margin:12px;border-radius:14px;color:#fff;padding:18px;display:flex;align-items:center;gap:12px}219.user-card .uc-avatar{width:56px;height:56px;border-radius:50%;background:rgba(255,255,255,.25);display:flex;align-items:center;justify-content:center;font-size:30px}220.user-card .uc-name{font-size:17px;font-weight:600}221.user-card .uc-level{font-size:12px;opacity:.9;margin-top:3px}222.order-entry{background:#fff;border-radius:12px;margin:12px;display:flex;padding:14px 0}223.order-entry a{flex:1;text-align:center;font-size:11px;color:#a4693b}224.order-entry a .oe-ico{font-size:22px;display:block;margin-bottom:4px;position:relative}225.order-entry a .oe-num{position:absolute;top:-6px;right:-8px;background:var(--red);color:#fff;border-radius:8px;font-size:9px;padding:1px 4px}226.menu-list{background:#fff;border-radius:12px;margin:12px;overflow:hidden}227.menu-list a{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid #f6ebdd;font-size:14px}228.menu-list a:last-child{border-bottom:none}229.menu-list a .ml-l{display:flex;align-items:center;gap:10px}230.menu-list a .ml-l .ico{font-size:20px}231.menu-list a .ml-r{color:#ccc;font-size:12px}232.empty{text-align:center;color:#c4a58a;font-size:13px;padding:40px 0}233.empty .e-icon{font-size:44px;display:block;margin-bottom:8px}234"""235236DATA = """// 小草面馆自助点餐 · 演示数据237window.DATA = {238 categories: ["招牌汤面", "干拌面", "凉菜小食", "加料浇头", "饮品"],239 sizes: ["小碗", "大碗"],240 spicy: ["不辣", "微辣", "中辣", "特辣"],241 toppings: [242 { name: "加卤蛋", price: 3 },243 { name: "加牛肉", price: 10 },244 { name: "加豆皮", price: 3 },245 { name: "加青菜", price: 2 },246 { name: "加面", price: 4 }247 ],248 noodles: [249 { id: 1, img: "🍜", name: "招牌红烧牛肉面", cat: "招牌汤面", price: 28, old: 32, sales: 15200, hot: true, new: false, tags: ["招牌必点", "大块牛肉"], desc: "慢炖三小时牛腩,汤头浓郁,面条筋道" },250 { id: 2, img: "🍅", name: "番茄鸡蛋面", cat: "招牌汤面", price: 22, old: 26, sales: 9800, hot: true, new: false, tags: ["酸甜开胃"], desc: "现炒番茄熬汤,两颗土鸡蛋" },251 { id: 3, img: "🌶️", name: "麻辣酸汤面", cat: "招牌汤面", price: 24, old: 28, sales: 8700, hot: false, new: true, tags: ["酸辣过瘾", "新品"], desc: "贵州糟辣椒 + 保宁醋,开胃解腻" },252 { id: 4, img: "🧅", name: "葱油拌面", cat: "干拌面", price: 18, old: 20, sales: 11200, hot: true, new: false, tags: ["葱香浓郁"], desc: "小葱熬油,拌开满碗飘香" },253 { id: 5, img: "🥢", name: "四川担担面", cat: "干拌面", price: 20, old: 24, sales: 7600, hot: false, new: false, tags: ["川味经典"], desc: "芽菜肉臊 + 花椒面,麻辣鲜香" },254 { id: 6, img: "🍜", name: "老北京炸酱面", cat: "干拌面", price: 21, old: 25, sales: 6500, hot: false, new: false, tags: ["酱香"], desc: "六必居黄酱,八种菜码" },255 { id: 7, img: "🌶️", name: "重庆酸辣粉", cat: "招牌汤面", price: 16, old: 18, sales: 13400, hot: true, new: false, tags: ["爽滑", "人气"], desc: "红油三椒,红薯粉 Q 弹" },256 { id: 8, img: "🥗", name: "红油凉皮", cat: "凉菜小食", price: 12, old: 14, sales: 9900, hot: true, new: false, tags: ["筋道"], desc: "汉中米皮,麻酱辣油凉拌" },257 { id: 9, img: "🍗", name: "卤味拼盘", cat: "凉菜小食", price: 19, old: 22, sales: 5400, hot: false, new: false, tags: ["下饭"], desc: "卤蛋 + 豆干 + 藕片,三拼" },258 { id: 10, img: "🥚", name: "秘制茶叶蛋", cat: "凉菜小食", price: 3, old: 0, sales: 8800, hot: false, new: false, tags: ["入味"], desc: "红茶八角慢卤,入味流心" },259 { id: 11, img: "🥤", name: "冰镇酸梅汤", cat: "饮品", price: 8, old: 10, sales: 12300, hot: true, new: false, tags: ["解腻"], desc: "乌梅山楂熬制,冰镇更爽" },260 { id: 12, img: "🥛", name: "现磨豆浆", cat: "饮品", price: 5, old: 0, sales: 6700, hot: false, new: false, tags: ["无糖"], desc: "东北非转基因黄豆,现磨" }261 ],262 combos: [263 { img: "🍜", name: "牛肉面套餐", price: 36, old: 39, desc: "红烧牛肉面 + 卤蛋 + 酸梅汤" },264 { img: "🥗", name: "凉皮套餐", price: 22, old: 26, desc: "凉皮 + 茶叶蛋 + 豆浆" }265 ],266 seckills: [267 { img: "🍜", name: "红烧牛肉面", price: 19.9, old: 28 },268 { img: "🥤", name: "酸梅汤", price: 4.9, old: 8 },269 { img: "🌶️", name: "酸辣粉", price: 11.9, old: 16 },270 { img: "🍅", name: "番茄鸡蛋面", price: 15.9, old: 22 }271 ],272 evals: [273 { avatar: "👩", name: "周女士", star: "★★★★★", text: "红烧牛肉面牛肉给得真多,汤头很鲜不咸,面也筋道,堂食外卖都点过好几次了。" },274 { avatar: "👨", name: "陈先生", star: "★★★★★", text: "自助点餐太方便了,坐下来扫码直接点,不用等服务员,上菜也快,翻台效率高。" },275 { avatar: "👩🦰", name: "林小姐", star: "★★★★☆", text: "酸辣粉够味,加面才 4 块很实在,就是中午人多要稍微等一下,整体满意。" }276 ],277 coupons: [278 { name: "新客立减券", val: "¥5", cond: "满 20 可用" },279 { name: "满减神券", val: "¥10", cond: "满 50 可用" },280 { name: "饮品券", val: "¥3", cond: "任意饮品可用" }281 ],282 recharge: [283 { val: "100", gift: "送 5 元券" },284 { val: "200", gift: "送 15 元券" },285 { val: "500", gift: "送 50 元券" }286 ],287 stores: [288 { name: "钟楼总店", dist: "1.1km", time: "10:00-22:00", addr: "东大街 118 号" },289 { name: "高新分店", dist: "3.2km", time: "10:30-21:30", addr: "高新路 26 号" },290 { name: "曲江店", dist: "4.8km", time: "11:00-21:00", addr: "芙蓉西路 9 号" }291 ],292 orderStatus: [293 { title: "已接单 · 厨房开始备餐", time: "12:30", done: true },294 { title: "制作中 · 煮面出锅装碗", time: "12:36", now: true },295 { title: "已出餐 · 请耐心等待上桌", time: "预计 12:42", done: false },296 { title: "已完成 · 慢用,欢迎再来", time: "", done: false }297 ]298};299"""300301APP = """// 小草面馆自助点餐 · 交互逻辑302document.addEventListener('click', function (e) {303 var t = e.target.closest('[data-toast]');304 if (t) { toast(t.getAttribute('data-toast')); }305 var ct = e.target.closest('.cat-tab');306 if (ct) {307 var wrap = ct.parentElement;308 [].forEach.call(wrap.children, function (x) { x.classList.remove('sel'); });309 ct.classList.add('sel');310 var kw = ct.textContent;311 var cards = document.querySelectorAll('.noodle-card');312 [].forEach.call(cards, function (c) {313 c.style.display = (kw === '全部' || c.getAttribute('data-cat') === kw) ? 'flex' : 'none';314 });315 }316 var so = e.target.closest('.sort-bar span');317 if (so) {318 var w2 = so.parentElement;319 [].forEach.call(w2.children, function (x) { x.classList.remove('on'); });320 so.classList.add('on');321 }322 var sp = e.target.closest('.spec-opt');323 if (sp) {324 var grp = sp.parentElement;325 [].forEach.call(grp.children, function (x) { x.classList.remove('sel'); });326 sp.classList.add('sel');327 }328 var sn = e.target.closest('.sr-num i');329 if (sn) {330 var b = sn.parentElement.querySelector('b');331 var v = parseInt(b.textContent) || 1;332 v = sn.textContent === '+' ? v + 1 : Math.max(1, v - 1);333 b.textContent = v;334 }335 var ci = e.target.closest('.ci-num i');336 if (ci) {337 var b = ci.parentElement.querySelector('b');338 var v = parseInt(b.textContent) || 1;339 v = ci.textContent === '+' ? v + 1 : Math.max(1, v - 1);340 b.textContent = v;341 }342 var ck = e.target.closest('.ci-check');343 if (ck) { ck.parentElement.classList.toggle('checked'); }344 var opt = e.target.closest('.cb-val .opt');345 if (opt) {346 var grp = opt.parentElement;347 [].forEach.call(grp.children, function (x) { x.classList.remove('sel'); });348 opt.classList.add('sel');349 }350 var pw = e.target.closest('.pw-item');351 if (pw) {352 var box = pw.parentElement;353 [].forEach.call(box.children, function (x) { x.classList.remove('sel'); });354 pw.classList.add('sel');355 }356 var sg = e.target.closest('.sign-btn');357 if (sg && !sg.classList.contains('done')) { sg.classList.add('done'); sg.textContent = '今日已签到 +10 积分'; toast('签到成功,积分 +10'); }358 var rg = e.target.closest('.recharge-opt');359 if (rg) {360 var grp = rg.parentElement;361 [].forEach.call(grp.children, function (x) { x.classList.remove('sel'); });362 rg.classList.add('sel');363 }364 var cp = e.target.closest('.cc-btn');365 if (cp) { cp.textContent = '已领取'; cp.style.opacity = '.6'; toast('优惠券已到账'); }366 var tb = e.target.closest('.table-box .tb-btn');367 if (tb) { toast('已识别桌号 A12,开始点餐'); }368});369// 秒杀倒计时370(function () {371 var box = document.querySelector('.sk-time');372 if (!box) return;373 var total = 1 * 3600 + 47 * 60 + 12;374 setInterval(function () {375 total--;376 if (total < 0) total = 86399;377 var h = Math.floor(total / 3600), m = Math.floor(total % 3600 / 60), s = total % 60;378 var z = function (n) { return n < 10 ? '0' + n : '' + n; };379 box.innerHTML = '<i>' + z(h) + '</i>:<i>' + z(m) + '</i>:<i>' + z(s) + '</i>';380 }, 1000);381})();382function toast(msg) {383 var d = document.createElement('div');384 d.style.cssText = 'position:fixed;left:50%;bottom:110px;transform:translateX(-50%);background:rgba(122,45,18,.92);color:#fff;padding:10px 20px;border-radius:20px;font-size:13px;z-index:999';385 d.textContent = msg;386 document.body.appendChild(d);387 setTimeout(function () { d.remove(); }, 1800);388}389"""390391def page(title, active, body, tabbar):392 # 把 body 中的内联渲染脚本(依赖 window.DATA)提取出来,放到 data.js 之后执行,393 # 否则脚本在 data.js 加载前运行会因 window.DATA 未定义而渲染失败(列表为空)。394 inline_scripts = re.findall(r'<script>(.*?)</script>', body, re.S)395 body_clean = re.sub(r'<script>.*?</script>', '', body, flags=re.S)396 inline_html = "".join("<script>" + s + "</script>" for s in inline_scripts)397 return """<!DOCTYPE html>398<html lang="zh-CN">399<head>400<meta charset="UTF-8"/>401<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"/>402<title>""" + title + """</title>403<link rel="stylesheet" href="style.css"/>404</head>405<body>406""" + body_clean + """407""" + tabbar + """408<script src="data.js"></script>409""" + inline_html + """410<script src="app.js"></script>411</body>412</html>"""413414def tabbar(active):415 items = [416 ("index.html", "🏠", "首页"),417 ("category.html", "🍜", "菜单"),418 ("cart.html", "🛒", "购物车"),419 ("member.html", "👑", "会员"),420 ("mine.html", "👤", "我的"),421 ]422 h = '<nav class="tabbar">'423 for href, icon, name in items:424 cls = ' active' if name == active else ''425 h += '<a class="' + cls + '" href="' + href + '"><span class="icon">' + icon + '</span>' + name + '</a>'426 return h + '</nav>'427428def header(title, back=True, right=""):429 b = '<a class="back" onclick="history.back()">‹</a>' if back else '<span class="back"></span>'430 return '<header class="header">' + b + '<h1>' + title + '</h1><span class="right">' + right + '</span></header>'431432INDEX = """433<div class="banner">434 <div>435 <div class="bn-title">小草面馆</div>436 <div class="bn-sub">扫码自助点餐 · 现煮现做<br/>招牌牛肉面 · 12 年地道老味道 · 上菜快翻台高</div>437 <div class="bn-badge">🎁 新客首单立减 5 元</div>438 </div>439 <div class="bn-emoji">🍜</div>440</div>441<div class="table-box" data-toast="已识别桌号 A12,开始点餐">442 <div class="tb-ico">📍</div>443 <div class="tb-body"><b>请选择桌号 / 扫码点餐</b><span>入座后点击识别桌号,本桌 3 人可一起拼单</span></div>444 <div class="tb-btn">识别桌号</div>445</div>446<div class="seckill">447 <div class="sk-head"><b>⚡ 限时秒杀</b><div class="sk-time"><i>01</i>:<i>47</i>:<i>12</i></div></div>448 <div class="sk-body" id="skList"></div>449</div>450<div class="quick-grid">451 <a href="category.html"><div class="qicon">🍜</div>全部面品</a>452 <a data-toast="本桌 3 人正在拼单"><div class="qicon">👥</div>多人拼单</a>453 <a href="cart.html"><div class="qicon">🛒</div>购物车</a>454 <a href="member.html"><div class="qicon">🎁</div>领券中心</a>455 <a data-toast="邀请好友各得 5 元券"><div class="qicon">🤝</div>邀请有礼</a>456</div>457<div class="coupon-card">458 <div class="cc-left"><b>新客立减 5 元无门槛券</b><span>全场通用 · 7 天内有效</span></div>459 <div class="cc-btn">立即领取</div>460</div>461<div class="section-title">🔥 招牌推荐 <span>月售 10 万+</span></div>462<div class="noodle-card" data-toast="已加入购物车">463 <div class="nc-img">🍜</div>464 <div class="nc-body">465 <div class="nc-name">招牌红烧牛肉面 <span class="badge badge-hot">招牌</span></div>466 <div class="nc-desc">慢炖三小时牛腩,汤头浓郁,面条筋道</div>467 <div class="nc-meta">月销 1.5 万+ · 大块牛肉</div>468 <div class="nc-foot"><div class="nc-price">¥28<small> /原32</small></div><div class="nc-add">+</div></div>469 </div>470</div>471<div class="section-title">🍱 超值套餐</div>472<div id="comboList"></div>473<div class="section-title">🏪 门店导航</div>474<div id="storeList"></div>475<script>476 var sk = document.getElementById('skList');477 var h = '';478 window.DATA.seckills.forEach(function (x) {479 h += '<div class="sk-item"><div class="sk-img">' + x.img + '</div><div class="sk-name">' + x.name + '</div>'480 + '<div class="sk-price">¥' + x.price + '</div><div class="sk-old">¥' + x.old + '</div></div>';481 });482 sk.innerHTML = h;483 var cl = document.getElementById('comboList');484 var h2 = '';485 window.DATA.combos.forEach(function (c) {486 h2 += '<div class="noodle-card"><div class="nc-img">' + c.img + '</div><div class="nc-body">'487 + '<div class="nc-name">' + c.name + ' <span class="badge badge-sale">套餐</span></div>'488 + '<div class="nc-desc">' + c.desc + '</div>'489 + '<div class="nc-foot"><div class="nc-price">¥' + c.price + '<small> /原' + c.old + '</small></div>'490 + '<div class="nc-add" data-toast="套餐已加入购物车">+</div></div></div></div>';491 });492 cl.innerHTML = h2;493 var sl = document.getElementById('storeList');494 var h3 = '';495 window.DATA.stores.slice(0, 2).forEach(function (s) {496 h3 += '<div class="noodle-card"><div class="nc-img">🏪</div><div class="nc-body">'497 + '<div class="nc-name">' + s.name + ' <span class="tag">' + s.dist + '</span></div>'498 + '<div class="nc-desc">' + s.addr + ' · 营业 ' + s.time + '</div>'499 + '<div class="nc-foot"><div class="nc-price" style="color:#c2410c;font-size:13px">' + s.dist + '</div>'500 + '<div class="nc-add" data-toast="已选择该门店">导航</div></div></div></div>';501 });502 sl.innerHTML = h3;503</script>504"""505506CATEGORY = """507""" + header("菜单点餐", back=False, right="🔍") + """508<div class="cat-tabs"></div>509<div class="sort-bar"><span class="on">综合排序</span><span>销量优先</span><span>价格从低到高</span></div>510<div id="catList"></div>511<div class="cart-float">512 <div class="cf-cart"><span class="ico">🛒<span class="num">3</span></span>合计</div>513 <div class="cf-total"><b>¥62</b></div>514 <div class="cf-btn" data-toast="已跳转购物车">去购物车</div>515</div>516<script>517 var ctw = document.querySelector('.cat-tabs');518 var h0 = '<div class="cat-tab sel">全部</div>';519 window.DATA.categories.forEach(function (c) {520 h0 += '<div class="cat-tab">' + c + '</div>';521 });522 ctw.innerHTML = h0;523 var cl = document.getElementById('catList');524 var h = '';525 window.DATA.noodles.forEach(function (b) {526 h += '<div class="noodle-card" data-cat="' + b.cat + '"><div class="nc-img">' + b.img + '</div><div class="nc-body">'527 + '<div class="nc-name">' + b.name + (b.hot ? ' <span class="badge badge-hot">热销</span>' : '') + (b.new ? ' <span class="badge badge-new">新品</span>' : '') + '</div>'528 + '<div class="nc-desc">' + b.desc + '</div>'529 + '<div class="nc-meta">月销 ' + b.sales.toLocaleString() + '+ · ' + b.tags.join('/') + '</div>'530 + '<div class="nc-foot"><div class="nc-price">¥' + b.price + (b.old ? '<small> /原' + b.old + '</small>' : '') + '</div>'531 + '<div class="nc-add" data-toast="已加入购物车">+</div></div></div></div>';532 });533 cl.innerHTML = h;534</script>535"""536537DETAIL = """538""" + header("商品详情") + """539<div class="detail-img"><div class="di-badge">📷 8 张实拍</div>🍜</div>540<div class="detail-price">541 <div class="dp-num">¥28<small> /小碗</small> <span style="color:#dc2626;font-size:13px">大碗 +4 元</span></div>542 <div class="dp-meta">招牌红烧牛肉面 · 慢炖三小时牛腩 · 汤头浓郁 · 面条现煮筋道 · 堂食外卖均可</div>543 <div class="dp-row">544 <div class="dp-cell">🏷️ 月销 1.5 万+</div>545 <div class="dp-cell">🔥 招牌必点</div>546 <div class="dp-cell">⏱️ 出餐 8 分钟</div>547 <div class="dp-cell">💯 不好吃退</div>548 </div>549</div>550<div class="spec-box">551 <div class="sb-title">选择规格</div>552 <div class="spec-row"><span class="sr-label">份量</span><div class="sr-opts"><div class="spec-opt sel">小碗 ¥28</div><div class="spec-opt">大碗 ¥32</div></div></div>553 <div class="spec-row"><span class="sr-label">辣度</span><div class="sr-opts"><div class="spec-opt">不辣</div><div class="spec-opt sel">微辣</div><div class="spec-opt">中辣</div><div class="spec-opt">特辣</div></div></div>554 <div class="spec-row"><span class="sr-label">加料</span><div class="sr-opts"><div class="spec-opt">加卤蛋 +3</div><div class="spec-opt">加牛肉 +10</div><div class="spec-opt">加豆皮 +3</div><div class="spec-opt">加青菜 +2</div><div class="spec-opt">加面 +4</div></div></div>555 <div class="spec-row"><span class="sr-label">数量</span><div class="sr-num"><i>-</i><b>1</b><i>+</i></div></div>556</div>557<div class="section-title">📋 关于这碗面</div>558<div class="card" style="margin-top:0;font-size:12px;color:#6b4a30;line-height:2">559 汤底:牛骨 + 鸡架文火熬制 4 小时,不勾兑<br/>560 面条:手工碱水面,现煮 90 秒,爽滑筋道<br/>561 牛肉:Inner Mongolia 牛腩,慢炖入味,大块不碎<br/>562 服务:堂食 8 分钟出餐 · 外卖 30 分钟达 · 不好吃可退563</div>564<div class="section-title">💬 用户评价(2980+)</div>565<div id="evalList"></div>566<div class="section-title">❤️ 猜你喜欢</div>567<div id="guessList" style="display:flex;gap:10px;overflow-x:auto;padding:0 12px;scrollbar-width:none"></div>568<div style="height:70px"></div>569<div class="buy-bar">570 <div class="bb-cart"><span class="ico">🛒<span class="num">3</span></span>购物车</div>571 <div class="bb-btn buy" data-toast="已加入购物车">加入购物车</div>572 <div class="bb-btn now" data-toast="订单提交成功">立即购买</div>573</div>574<script>575 var el = document.getElementById('evalList');576 var h = '';577 window.DATA.evals.forEach(function (x) {578 h += '<div class="eval-card"><div class="ev-head"><div class="ev-avatar">' + x.avatar + '</div>'579 + '<div>' + x.name + '</div><div class="ev-star">' + x.star + '</div>'580 + '</div><div class="ev-text">' + x.text + '</div></div>';581 });582 el.innerHTML = h;583 var gl = document.getElementById('guessList');584 var h2 = '';585 window.DATA.noodles.slice(1, 5).forEach(function (b) {586 h2 += '<div class="sk-item" style="width:110px"><div class="sk-img" style="height:80px">' + b.img + '</div>'587 + '<div class="sk-name">' + b.name + '</div><div class="sk-price">¥' + b.price + '</div></div>';588 });589 gl.innerHTML = h2;590</script>591"""592593CART = """594""" + header("购物车") + """595<div class="cart-item checked">596 <div class="ci-check">✓</div>597 <div class="ci-img">🍜</div>598 <div class="ci-body">599 <div class="ci-name">招牌红烧牛肉面 <span class="badge badge-hot">招牌</span></div>600 <div class="ci-spec">大碗 · 微辣 · 加卤蛋</div>601 <div class="ci-foot"><div class="ci-price">¥31</div><div class="ci-num"><i>-</i><b>1</b><i>+</i></div></div>602 </div>603</div>604<div class="cart-item checked">605 <div class="ci-check">✓</div>606 <div class="ci-img">🥤</div>607 <div class="ci-body">608 <div class="ci-name">冰镇酸梅汤</div>609 <div class="ci-spec">冰 · 大杯</div>610 <div class="ci-foot"><div class="ci-price">¥8</div><div class="ci-num"><i>-</i><b>2</b><i>+</i></div></div>611 </div>612</div>613<div class="cart-item">614 <div class="ci-check"></div>615 <div class="ci-img">🌶️</div>616 <div class="ci-body">617 <div class="ci-name">重庆酸辣粉 <span class="badge badge-new">人气</span></div>618 <div class="ci-spec">中辣 · 加面</div>619 <div class="ci-foot"><div class="ci-price">¥20</div><div class="ci-num"><i>-</i><b>1</b><i>+</i></div></div>620 </div>621</div>622<div class="coupon-card" style="margin-top:12px">623 <div class="cc-left"><b>满 50 减 10 神券</b><span>购物车金额 67 元 · 已自动抵扣</span></div>624 <div class="cc-btn">已用券</div>625</div>626<div class="check-box">627 <div class="cb-row"><span class="cb-label">桌号</span><span class="cb-val">A12 桌 <span class="tag">3 人拼单</span></span></div>628 <div class="cb-row"><span class="cb-label">取餐方式</span><span class="cb-val"><span class="opt sel">🍽️ 堂食</span><span class="opt">🥡 到店自提</span><span class="opt">🛵 外卖</span></span></div>629 <div class="cb-row"><span class="cb-label">自提门店</span><span class="cb-val dim">钟楼总店(1.1km)›</span></div>630 <div class="cb-row"><span class="cb-label">预约时间</span><span class="cb-val">现在 · 立即出餐 ›</span></div>631 <div class="cb-row"><span class="cb-label">订单备注</span><span class="cb-val dim">少辣 / 不要香菜 ›</span></div>632</div>633<div style="height:80px"></div>634<div class="settle-bar">635 <div class="sb-all"><span class="ci-check">✓</span>全选</div>636 <div class="sb-total">合计 <b>¥57</b><br/>已优惠 ¥10</div>637 <div class="sb-btn" data-toast="已跳转结算">去结算</div>638</div>639"""640641ORDER = """642""" + header("确认订单") + """643<div class="pay-card">644 <div class="pc-row"><span class="pc-label">取餐方式</span><span class="pc-val">🍽️ 堂食 · A12 桌(3 人拼单)</span></div>645 <div class="pc-row"><span class="pc-label">自提门店</span><span class="pc-val dim">钟楼总店 · 东大街 118 号 ›</span></div>646 <div class="pc-row"><span class="pc-label">预约时间</span><span class="pc-val">现在 · 立即出餐</span></div>647 <div class="pc-row"><span class="pc-label">订单备注</span><span class="pc-val dim">少辣 / 不要香菜 ›</span></div>648</div>649<div class="card" style="margin-top:-4px">650 <div style="display:flex;gap:10px;align-items:center;padding:6px 0"><div class="ci-img" style="width:48px;height:48px;border-radius:8px;background:var(--primary-light);display:flex;align-items:center;justify-content:center;font-size:22px">🍜</div><div style="flex:1;font-size:13px;font-weight:600">招牌红烧牛肉面</div><div style="font-size:12px;color:#9c8b7c">¥31</div></div>651 <div style="display:flex;gap:10px;align-items:center;padding:6px 0"><div class="ci-img" style="width:48px;height:48px;border-radius:8px;background:var(--primary-light);display:flex;align-items:center;justify-content:center;font-size:22px">🥤</div><div style="flex:1;font-size:13px;font-weight:600">冰镇酸梅汤 ×2</div><div style="font-size:12px;color:#9c8b7c">¥16</div></div>652</div>653<div class="pay-card" style="margin-top:-4px">654 <div class="pc-row"><span class="pc-label">优惠券</span><span class="pc-val" style="color:#dc2626">¥10 满减券 ▾</span></div>655 <div class="pc-row"><span class="pc-label">会员折扣</span><span class="pc-val" style="color:#16a34a">金卡 9 折 -¥5.7</span></div>656 <div class="pc-row"><span class="pc-label">实付金额</span><span class="pc-val"><b style="font-size:20px;color:var(--red)">¥41.3</b></span></div>657</div>658<div class="pay-way">659 <div class="pw-title">选择支付方式</div>660 <div class="pw-item sel"><span class="pw-ico">💚</span>微信支付<div class="pw-radio">✓</div></div>661 <div class="pw-item"><span class="pw-ico">💙</span>支付宝<div class="pw-radio"></div></div>662 <div class="pw-item"><span class="pw-ico">💳</span>会员储值余额(¥260)<div class="pw-radio"></div></div>663</div>664<div style="height:80px"></div>665<div class="settle-bar">666 <div class="sb-total" style="text-align:left">应付 <b>¥41.3</b></div>667 <div class="sb-btn" data-toast="支付成功,订单已提交">立即支付 ¥41.3</div>668</div>669"""670671ORDERS = """672""" + header("订单状态") + """673<div class="order-tabs">674 <a class="active">进行中</a><a>已完成</a><a>已取消</a>675</div>676<div class="order-card">677 <div class="oc-head"><span>A12 桌 · 2026-09-06 12:30 <span class="tag">单号 M202609061230</span></span><span class="st">制作中</span></div>678 <div class="oc-goods"><div class="og-img">🍜</div><div class="og-name">招牌红烧牛肉面<br/><span style="font-size:11px;color:#9c8b7c">大碗 · 微辣 · 加卤蛋</span></div><div class="og-price">¥31</div></div>679 <div class="oc-goods"><div class="og-img">🥤</div><div class="og-name">冰镇酸梅汤 ×2</div><div class="og-price">¥16</div></div>680 <div class="oc-foot"><span>共 3 件 · 实付</span><b>¥41.3</b></div>681 <div class="call-bar">682 <i data-toast="已呼叫服务员加水">💧 加水</i>683 <i data-toast="已呼叫加餐具">🥢 加餐具</i>684 <i class="main" data-toast="已呼叫服务员买单">🧾 呼叫买单</i>685 </div>686</div>687<div class="section-title">📡 实时进度</div>688<div class="status-line" id="statusList"></div>689<div class="order-card" style="margin-top:12px">690 <div class="oc-head"><span>A12 桌 · 2026-09-05 19:10</span><span class="st" style="color:#16a34a">已完成</span></div>691 <div class="oc-goods"><div class="og-img">🧅</div><div class="og-name">葱油拌面 ×1<br/><span style="font-size:11px;color:#9c8b7c">小碗 · 不辣</span></div><div class="og-price">¥18</div></div>692 <div class="oc-foot"><span>共 1 件 · 实付</span><b>¥18</b></div>693 <div class="oc-ops"><i class="main">去评价</i><i>再次点单</i></div>694</div>695<script>696 var sl = document.getElementById('statusList');697 var h = '';698 window.DATA.orderStatus.forEach(function (t) {699 var cls = t.now ? 'now' : (t.done ? 'done' : '');700 h += '<div class="sl-dot ' + cls + '"><div class="sl-c"></div><div>'701 + '<div class="sl-title">' + t.title + '</div><div class="sl-time">' + (t.time || '待处理') + '</div></div></div>';702 });703 sl.innerHTML = h;704</script>705"""706707MEMBER = """708""" + header("会员中心", back=False, right="⚙️") + """709<div class="vip-card">710 <div class="vc-level">👑 金卡会员 · 尊享 9 折</div>711 <div class="vc-name">金卡会员</div>712 <div class="vc-exp">距离钻石会员还差 280 成长值 · 到期 2027-09</div>713 <div class="vc-bar"><i></i></div>714</div>715<div class="assets">716 <div class="asset-item"><b>860</b><span>积分</span></div>717 <div class="asset-item"><b>¥260</b><span>储值余额</span></div>718 <div class="asset-item"><b>5 张</b><span>优惠券</span></div>719</div>720<div class="sign-btn">📅 每日签到 +10 积分</div>721<div class="section-title">🎯 会员特权</div>722<div class="vip-grid">723 <div class="vip-item" data-toast="会员价已生效"><div class="vi-emoji">🏷️</div><div class="vi-name">会员专享价</div><div class="vi-desc">金卡 9 折 · 银卡 95 折</div></div>724 <div class="vip-item" data-toast="每周三面馆日"><div class="vi-emoji">📅</div><div class="vi-name">会员福利日</div><div class="vi-desc">每周三全场折上折</div></div>725 <div class="vip-item" data-toast="生日当天 2 倍积分"><div class="vi-emoji">🎂</div><div class="vi-name">生日双倍积分</div><div class="vi-desc">生日月消费积分翻倍</div></div>726 <div class="vip-item" data-toast="参与积分抽奖"><div class="vi-emoji">🎰</div><div class="vi-name">积分抽奖</div><div class="vi-desc">100 积分抽免单</div></div>727 <div class="vip-item" data-toast="积分可当钱花"><div class="vi-emoji">🛍️</div><div class="vi-name">积分商城</div><div class="vi-desc">兑换面券 / 小食</div></div>728 <div class="vip-item" data-toast="新品尝鲜权已发放"><div class="vi-emoji">🍜</div><div class="vi-name">新品尝鲜权</div><div class="vi-desc">新品 5 折试吃</div></div>729</div>730<div class="section-title">💳 储值有礼</div>731<div class="recharge-box">732 <div class="rb-title">储值多充多赠 · 门店线上通用</div>733 <div class="recharge-opts">734 <div class="recharge-opt sel"><b>¥100</b><span>送 5 元券</span></div>735 <div class="recharge-opt"><b>¥200</b><span>送 15 元券</span></div>736 <div class="recharge-opt"><b>¥500</b><span>送 50 元券</span></div>737 </div>738 <div class="btn btn-gold" style="margin-top:14px" data-toast="充值成功,券已到账">立即充值</div>739</div>740<div class="section-title">🚀 赚钱与活动</div>741<div class="vip-grid">742 <div class="vip-item" data-toast="邀请 3 人成团享 8 折"><div class="vi-emoji">👥</div><div class="vi-name">好友拼团</div><div class="vi-desc">3 人成团 8 折</div></div>743 <div class="vip-item" data-toast="已发起砍价"><div class="vi-emoji">🪓</div><div class="vi-name">邀请砍价</div><div class="vi-desc">砍到最低 5 折</div></div>744 <div class="vip-item" data-toast="分销佣金比例 8%"><div class="vi-emoji">💰</div><div class="vi-name">分享赚佣金</div><div class="vi-desc">好友下单返 8%</div></div>745 <div class="vip-item" data-toast="霸王餐已开启"><div class="vi-emoji">🍜</div><div class="vi-name">霸王餐抽奖</div><div class="vi-desc">每日抽免单券</div></div>746</div>747"""748749MINE = """750<div class="user-card">751 <div class="uc-avatar">🧑🍳</div>752 <div>753 <div class="uc-name">资深面友</div>754 <div class="uc-level">👑 金卡会员 · 成长值 1720 · 累计省 ¥186</div>755 </div>756</div>757<div class="order-entry">758 <a data-toast="1 单制作中"><span class="oe-ico">🍳</span>进行中<span class="oe-num">1</span></a>759 <a data-toast="暂无待付款"><span class="oe-ico">💰</span>待付款</a>760 <a data-toast="暂无待自提"><span class="oe-ico">🥡</span>待自提</a>761 <a data-toast="1 单待评价"><span class="oe-ico">⭐</span>待评价<span class="oe-num">1</span></a>762 <a data-toast="无退款"><span class="oe-ico">↩️</span>退款</a>763</div>764<div class="menu-list">765 <a href="orders.html"><span class="ml-l"><span class="ico">🧾</span>我的订单</span><span class="ml-r">›</span></a>766 <a href="member.html"><span class="ml-l"><span class="ico">👑</span>会员中心</span><span class="ml-r">›</span></a>767 <a data-toast="常用桌号 A12"><span class="ml-l"><span class="ico">📍</span>我的桌号</span><span class="ml-r">A12</span></a>768 <a data-toast="余额 ¥260"><span class="ml-l"><span class="ico">💳</span>我的余额</span><span class="ml-r">¥260</span></a>769 <a data-toast="积分 860"><span class="ml-l"><span class="ico">⭐</span>我的积分</span><span class="ml-r">860</span></a>770 <a data-toast="优惠券 5 张可用"><span class="ml-l"><span class="ico">🎟️</span>优惠券</span><span class="ml-r">5 张</span></a>771 <a data-toast="收藏 8 道面"><span class="ml-l"><span class="ico">❤️</span>我的收藏</span><span class="ml-r">8</span></a>772 <a data-toast="邀请好友各得 5 元券"><span class="ml-l"><span class="ico">🤝</span>邀请有礼</span><span class="ml-r">›</span></a>773 <a data-toast="客服在线 10:00-22:00"><span class="ml-l"><span class="ico">🎧</span>联系客服</span><span class="ml-r">400-800-8866</span></a>774</div>775"""776777README = """# 小草面馆自助点餐(移动端 H5)778779面馆扫码自助点餐一体化平台,功能对标海底捞/西贝/和府捞面等头部餐饮自助点餐小程序,纯原生零依赖,移动端优先(390×844)。780781## 页面(8 页)782- index.html 首页:品牌 Banner、桌号识别/扫码点餐入口、限时秒杀(倒计时)、5 大快捷入口(菜单/拼单/购物车/领券/邀请)、新客领券、招牌推荐、超值套餐、门店导航783- category.html 菜单:分类切换(招牌汤面/干拌面/凉菜小食/加料浇头/饮品)、综合/销量/价格排序、菜品卡(图/名/价/月售/标签/加购)、底部购物车浮条(合计金额/件数)784- detail.html 商品详情:规格(份量/辣度/加料)多选、数量步进、关于这碗面、用户评价、猜你喜欢、加入购物车/立即购买785- cart.html 购物车:多商品勾选、数量调整、满减券自动抵扣、取餐方式(堂食/到店自提/外卖)、自提门店+预约时间、备注、全选结算786- order.html 确认订单:取餐方式/门店/时间/备注确认、商品清单、优惠券+会员折扣、实付金额、支付方式(微信/支付宝/储值)、立即支付787- orders.html 订单状态:进行中/已完成/已取消 Tab、订单卡(单号/呼叫加水/加餐具/买单)、实时进度时间线(已接单→制作中→已出餐→已完成)788- member.html 会员中心:会员等级卡(成长值进度)、积分/储值/券资产、每日签到、会员特权(专享价/福利日/生日双倍/积分抽奖/积分商城/新品尝鲜)、储值多充多赠、拼团/砍价/分销/霸王餐789- mine.html 个人中心:会员卡、订单快捷入口(进行中/待付款/自提/评价/退款)、桌号/余额/积分/优惠券/收藏/邀请有礼/客服790791## 文件792- style.css 移动端优先样式(红汤橙红主题)793- app.js 零依赖交互逻辑(秒杀倒计时/分类筛选/规格选择/数量步进/签到/领券/支付选择/Toast)794- data.js 演示数据集中管理(商品/套餐/秒杀/门店/评价/优惠券/储值档位/订单状态)795"""796797def main():798 files = {799 "index.html": page("首页 · 小草面馆自助点餐", "index", INDEX, tabbar("首页")),800 "category.html": page("菜单点餐 · 小草面馆", "category", CATEGORY, tabbar("菜单")),801 "detail.html": page("商品详情 · 小草面馆", "detail", DETAIL, tabbar("菜单")),802 "cart.html": page("购物车 · 小草面馆", "cart", CART, tabbar("购物车")),803 "order.html": page("确认订单 · 小草面馆", "order", ORDER, tabbar("我的")),804 "orders.html": page("订单状态 · 小草面馆", "orders", ORDERS, tabbar("我的")),805 "member.html": page("会员中心 · 小草面馆", "member", MEMBER, tabbar("会员")),806 "mine.html": page("个人中心 · 小草面馆", "mine", MINE, tabbar("我的")),807 "style.css": CSS,808 "data.js": DATA,809 "app.js": APP,810 "README.md": README,811 }812 for name, content in files.items():813 with open(os.path.join(OUT, name), "w", encoding="utf-8") as f:814 f.write(content)815 print(" +", name)816817if __name__ == "__main__":818 main()819