某杰蔬菜批发配送_H5/gen.py · 约 65087 字符
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:#f3faef;color:#1f3d1a;max-width:430px;margin:0 auto;min-height:100vh}12a{text-decoration:none;color:inherit}13ul{list-style:none}14:root{--primary:#16a34a;--primary-dark:#15803d;--primary-light:#dcfce7;--secondary:#22c55e;--accent:#65a30d;--dark:#14532d;--gray:#9bbf93;--light-gray:#eaf5e4;--green:#16a34a;--blue:#2563eb;--orange:#ea580c;--red:#dc2626;--gold:#ca8a04}15.header{background:linear-gradient(135deg,#15803d,#16a34a);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(21,128,61,.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,#15803d,#16a34a);color:#fff}28.btn-gold{background:linear-gradient(135deg,#ca8a04,#eab308);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-org{background:#dcfce7;color:var(--primary-dark)}36.tag{display:inline-block;padding:2px 6px;border-radius:4px;font-size:11px;background:var(--light-gray);color:#2f6b28;margin:2px 4px 0 0}37/* 首页 */38.banner{height:160px;margin:12px;border-radius:14px;background:linear-gradient(135deg,#14532d,#16a34a,#84cc16);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.search-box{margin:12px;background:#fff;border-radius:22px;padding:11px 16px;display:flex;align-items:center;gap:8px;box-shadow:0 1px 4px rgba(0,0,0,.05)}44.search-box .s-ico{font-size:18px}45.search-box input{border:none;outline:none;flex:1;font-size:13px;color:#1f3d1a}46.search-box .s-btn{background:linear-gradient(135deg,#15803d,#16a34a);color:#fff;padding:6px 14px;border-radius:16px;font-size:12px;font-weight:700}47.cat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;padding:0 12px}48.cat-grid a{background:#fff;border-radius:12px;padding:14px 4px;text-align:center;box-shadow:0 1px 4px rgba(0,0,0,.04)}49.cat-grid a .c-emoji{font-size:28px;display:block}50.cat-grid a .c-name{font-size:12px;margin-top:6px;color:#2f6b28;font-weight:600}51.quick-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:6px;padding:16px 10px;background:#fff;margin:12px;border-radius:14px}52.quick-grid a{text-align:center;font-size:11px;color:#2f6b28}53.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}54.price-news{background:#fff;border-radius:14px;margin:12px;padding:14px;box-shadow:0 1px 4px rgba(0,0,0,.05)}55.price-news .pn-head{display:flex;align-items:center;gap:8px;font-size:14px;font-weight:700}56.price-news .pn-head .pn-tag{background:#dcfce7;color:var(--primary-dark);font-size:11px;padding:2px 8px;border-radius:10px}57.price-news .pn-item{display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px solid #f0f7ec;font-size:12px}58.price-news .pn-item:last-child{border-bottom:none}59.price-news .pn-item .pn-name{flex:1}60.price-news .pn-item .pn-price{font-weight:700;color:var(--primary-dark)}61.price-news .pn-item .pn-chg.up{color:var(--red)}62.price-news .pn-item .pn-chg.down{color:var(--green)}63.seckill{background:#fff;border-radius:14px;margin:12px;overflow:hidden;box-shadow:0 1px 4px rgba(0,0,0,.05)}64.seckill .sk-head{background:linear-gradient(135deg,#dc2626,#ea580c);color:#fff;padding:10px 14px;display:flex;align-items:center;gap:10px}65.seckill .sk-head b{font-size:15px}66.seckill .sk-head .sk-time{display:flex;gap:3px;margin-left:auto}67.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}68.seckill .sk-body{display:flex;gap:10px;padding:12px;overflow-x:auto;scrollbar-width:none}69.seckill .sk-item{width:96px;flex-shrink:0;text-align:center}70.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}71.seckill .sk-item .sk-name{font-size:11px;margin-top:4px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}72.seckill .sk-item .sk-price{color:var(--red);font-weight:800;font-size:14px;margin-top:2px}73.seckill .sk-item .sk-old{color:#b6c9af;font-size:10px;text-decoration:line-through}74.veg-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)}75.veg-card .vc-img{width:92px;height:92px;border-radius:10px;background:linear-gradient(135deg,#dcfce7,#bbf7d0);display:flex;align-items:center;justify-content:center;font-size:44px;flex-shrink:0}76.veg-card .vc-body{flex:1;min-width:0}77.veg-card .vc-name{font-size:14px;font-weight:700}78.veg-card .vc-desc{font-size:11px;color:#9bbf93;margin-top:3px}79.veg-card .vc-meta{font-size:10px;color:#a8c2a0;margin-top:3px}80.veg-card .vc-foot{display:flex;justify-content:space-between;align-items:center;margin-top:6px}81.veg-card .vc-price{color:var(--red);font-weight:800;font-size:17px}82.veg-card .vc-price small{font-size:11px;color:#9bbf93;font-weight:400}83.veg-card .vc-add{background:linear-gradient(135deg,#15803d,#16a34a);color:#fff;width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:17px;font-weight:700}84/* 采购分类 */85.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:#f3faef}86.cat-tab{padding:8px 14px;border:1px solid #cfe8c4;border-radius:20px;font-size:12px;cursor:pointer;background:#fff;white-space:nowrap;flex-shrink:0}87.cat-tab.sel{border-color:var(--primary);background:var(--primary-light);color:var(--primary-dark);font-weight:600}88.sort-bar{display:flex;gap:14px;padding:10px 12px;font-size:13px;color:#2f6b28}89.sort-bar span.on{color:var(--primary);font-weight:700}90.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)}91.cart-float .cf-cart{display:flex;align-items:center;gap:6px;font-size:12px;color:#2f6b28}92.cart-float .cf-cart .ico{font-size:24px;position:relative}93.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}94.cart-float .cf-total{flex:1;text-align:right;font-size:12px;color:#9bbf93}95.cart-float .cf-total b{color:var(--red);font-size:18px}96.cart-float .cf-btn{background:linear-gradient(135deg,#15803d,#16a34a);color:#fff;border-radius:20px;padding:11px 22px;font-size:14px;font-weight:600}97/* 详情 */98.detail-img{height:230px;background:linear-gradient(135deg,#dcfce7,#bbf7d0);display:flex;align-items:center;justify-content:center;font-size:84px;position:relative}99.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}100.detail-price{background:#fff;margin:12px;border-radius:14px;padding:16px}101.detail-price .dp-num{font-size:26px;font-weight:800;color:var(--red)}102.detail-price .dp-num small{font-size:12px;color:#999}103.detail-price .dp-meta{font-size:12px;color:#9bbf93;margin-top:4px;line-height:1.7}104.detail-price .dp-row{display:flex;gap:8px;margin-top:10px}105.detail-price .dp-cell{flex:1;background:var(--light-gray);border-radius:10px;padding:8px;text-align:center;font-size:11px;color:#2f6b28}106.tier-box{background:#fff;margin:12px;border-radius:14px;padding:16px}107.tier-box .tb-title{font-size:14px;font-weight:700;margin-bottom:10px;display:flex;align-items:center;gap:6px}108.tier-row{display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px solid #f0f7ec;font-size:13px}109.tier-row:last-child{border-bottom:none}110.tier-row .tr-label{width:96px;color:#2f6b28;flex-shrink:0}111.tier-row .tr-price{flex:1;text-align:right;font-weight:700;color:var(--primary-dark)}112.tier-row .tr-price b{font-size:16px}113.tier-row.cur{background:var(--primary-light);border-radius:8px;margin:0 -8px;padding:9px 8px}114.tier-row.cur .tr-label{color:var(--primary-dark);font-weight:700}115.spec-box{background:#fff;margin:12px;border-radius:14px;padding:16px}116.spec-box .sb-title{font-size:14px;font-weight:700;margin-bottom:10px}117.spec-row{display:flex;align-items:center;gap:10px;padding:8px 0;border-bottom:1px solid #f0f7ec}118.spec-row:last-child{border-bottom:none}119.spec-row .sr-label{width:70px;font-size:13px;color:#2f6b28;flex-shrink:0}120.spec-row .sr-opts{display:flex;gap:8px;flex:1;flex-wrap:wrap}121.spec-opt{padding:6px 12px;border:1px solid #cfe8c4;border-radius:14px;font-size:12px;cursor:pointer;background:#fff}122.spec-opt.sel{border-color:var(--primary);background:var(--primary-light);color:var(--primary-dark);font-weight:600}123.spec-row .sr-num{display:flex;align-items:center;gap:8px;margin-left:auto}124.spec-row .sr-num i{width:26px;height:26px;border:1px solid #cfe8c4;border-radius:50%;display:flex;align-items:center;justify-content:center;font-style:normal;cursor:pointer}125.eval-card{background:#fff;border-radius:14px;margin:10px 12px;padding:12px;box-shadow:0 1px 4px rgba(0,0,0,.05)}126.eval-card .ev-head{display:flex;align-items:center;gap:8px;font-size:12px}127.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}128.eval-card .ev-star{color:var(--accent);font-size:11px}129.eval-card .ev-text{font-size:12px;color:#3c5a35;line-height:1.7;margin-top:6px}130.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}131.buy-bar .bb-cart{display:flex;align-items:center;gap:6px;font-size:12px;color:#2f6b28}132.buy-bar .bb-cart .ico{font-size:24px;position:relative}133.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}134.buy-bar .bb-btn{flex:1;border-radius:20px;padding:11px;text-align:center;color:#fff;font-size:14px;font-weight:600}135.buy-bar .bb-btn.buy{background:linear-gradient(135deg,#ca8a04,#eab308)}136.buy-bar .bb-btn.now{background:linear-gradient(135deg,#15803d,#16a34a)}137/* 进货单 */138.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)}139.cart-item .ci-check{width:22px;height:22px;border-radius:50%;border:2px solid #bfdcb2;flex-shrink:0;display:flex;align-items:center;justify-content:center;color:#fff;font-size:12px}140.cart-item.checked .ci-check{background:var(--primary);border-color:var(--primary)}141.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}142.cart-item .ci-body{flex:1;min-width:0}143.cart-item .ci-name{font-size:13px;font-weight:700}144.cart-item .ci-spec{font-size:11px;color:#9bbf93;margin-top:2px}145.cart-item .ci-foot{display:flex;justify-content:space-between;align-items:center;margin-top:6px}146.cart-item .ci-price{color:var(--red);font-weight:800}147.cart-item .ci-num{display:flex;align-items:center;gap:8px}148.cart-item .ci-num i{width:24px;height:24px;border:1px solid #cfe8c4;border-radius:50%;display:flex;align-items:center;justify-content:center;font-style:normal;font-size:13px}149.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}150.settle-bar .sb-all{display:flex;align-items:center;gap:6px;font-size:12px;color:#2f6b28}151.settle-bar .sb-total{flex:1;text-align:right;font-size:12px;color:#9bbf93}152.settle-bar .sb-total b{color:var(--red);font-size:18px}153.settle-bar .sb-btn{background:linear-gradient(135deg,#15803d,#16a34a);color:#fff;border-radius:20px;padding:11px 26px;font-size:14px;font-weight:600}154.check-box{background:#fff;border-radius:14px;margin:12px;padding:16px}155.check-box .cb-row{display:flex;align-items:center;gap:10px;padding:10px 0;border-bottom:1px solid #f0f7ec;font-size:13px}156.check-box .cb-row:last-child{border-bottom:none}157.check-box .cb-label{width:86px;color:#2f6b28;flex-shrink:0}158.check-box .cb-val{flex:1;text-align:right;color:#1f3d1a}159.check-box .cb-val.dim{color:#a8c2a0}160.check-box .cb-val .opt{padding:5px 10px;border:1px solid #cfe8c4;border-radius:12px;font-size:12px;margin-left:6px}161.check-box .cb-val .opt.sel{border-color:var(--primary);background:var(--primary-light);color:var(--primary-dark)}162/* 提交订单 */163.pay-card{background:#fff;border-radius:14px;margin:12px;padding:16px}164.pay-card .pc-row{display:flex;align-items:center;gap:10px;padding:11px 0;border-bottom:1px solid #f0f7ec;font-size:13px}165.pay-card .pc-row:last-child{border-bottom:none}166.pay-card .pc-label{width:72px;color:#2f6b28;flex-shrink:0}167.pay-card .pc-val{flex:1;color:#1f3d1a}168.pay-card .pc-val.dim{color:#a8c2a0}169.pay-way{background:#fff;border-radius:14px;margin:12px;padding:16px}170.pay-way .pw-title{font-size:14px;font-weight:700;margin-bottom:8px}171.pay-way .pw-item{display:flex;align-items:center;gap:10px;padding:12px 0;border-bottom:1px solid #f0f7ec;font-size:14px}172.pay-way .pw-item:last-child{border-bottom:none}173.pay-way .pw-ico{font-size:24px}174.pay-way .pw-radio{margin-left:auto;width:20px;height:20px;border-radius:50%;border:2px solid #bfdcb2;display:flex;align-items:center;justify-content:center;color:#fff;font-size:11px}175.pay-way .pw-item.sel .pw-radio{background:var(--primary);border-color:var(--primary)}176/* 订单/配送状态 */177.order-tabs{display:flex;background:#fff;border-bottom:1px solid #f0f7ec;position:sticky;top:0;z-index:99}178.order-tabs a{flex:1;text-align:center;padding:12px 4px;font-size:13px;color:#2f6b28;position:relative}179.order-tabs a.active{color:var(--primary);font-weight:700}180.order-tabs a.active::after{content:"";position:absolute;bottom:0;left:25%;width:50%;height:3px;background:var(--primary);border-radius:3px}181.order-card{background:#fff;border-radius:14px;margin:10px 12px;padding:14px;box-shadow:0 1px 4px rgba(0,0,0,.05)}182.order-card .oc-head{display:flex;justify-content:space-between;font-size:12px;color:#9bbf93;padding-bottom:10px;border-bottom:1px solid #f0f7ec}183.order-card .oc-head .st{color:var(--primary);font-weight:700}184.order-card .oc-goods{display:flex;gap:10px;padding:10px 0;align-items:center}185.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}186.order-card .oc-goods .og-name{font-size:13px;font-weight:600;flex:1}187.order-card .oc-goods .og-price{font-size:12px;color:#9bbf93}188.order-card .oc-foot{display:flex;justify-content:space-between;align-items:center;font-size:12px;color:#9bbf93}189.order-card .oc-foot b{color:var(--red);font-size:15px}190.order-card .oc-ops{display:flex;gap:8px;margin-top:10px;justify-content:flex-end}191.order-card .oc-ops i{padding:6px 14px;border:1px solid #cfe8c4;border-radius:15px;font-style:normal;font-size:12px}192.order-card .oc-ops i.main{background:linear-gradient(135deg,#15803d,#16a34a);color:#fff;border-color:transparent}193.call-bar{display:flex;gap:8px;margin:10px 12px}194.call-bar i{flex:1;text-align:center;padding:9px 0;border:1px solid #cfe8c4;border-radius:14px;font-style:normal;font-size:12px;color:#2f6b28}195.call-bar i.main{background:var(--primary-light);color:var(--primary-dark);border-color:var(--primary);font-weight:600}196.status-line{background:#fff;border-radius:14px;margin:12px;padding:16px}197.status-line .sl-dot{display:flex;gap:12px;position:relative;padding-bottom:16px}198.status-line .sl-dot:last-child{padding-bottom:0}199.status-line .sl-c{width:14px;height:14px;border-radius:50%;background:#d6e9cf;flex-shrink:0;margin-top:2px;position:relative;z-index:1}200.status-line .sl-dot.done .sl-c{background:var(--green)}201.status-line .sl-dot.now .sl-c{background:var(--accent);box-shadow:0 0 0 4px #eef7df}202.status-line .sl-dot::before{content:"";position:absolute;left:6px;top:16px;bottom:-2px;width:2px;background:#e3f0dc}203.status-line .sl-dot:last-child::before{display:none}204.status-line .sl-title{font-size:13px;font-weight:600}205.status-line .sl-time{font-size:11px;color:#9bbf93;margin-top:2px}206.track-bar{background:#fff;border-radius:14px;margin:12px;padding:16px;display:flex;align-items:center;gap:12px}207.track-bar .tb-ico{font-size:30px}208.track-bar .tb-body{flex:1}209.track-bar .tb-body b{font-size:14px}210.track-bar .tb-body span{font-size:11px;color:#9bbf93;display:block;margin-top:2px}211.track-bar .tb-btn{background:var(--primary-light);color:var(--primary-dark);padding:8px 14px;border-radius:16px;font-size:12px;font-weight:700}212/* 会员/客户中心 */213.vip-card{background:linear-gradient(135deg,#14532d,#15803d,#65a30d);margin:12px;border-radius:16px;color:#fff;padding:20px;position:relative;overflow:hidden}214.vip-card::after{content:"VIP";position:absolute;right:12px;top:10px;font-size:40px;font-weight:800;opacity:.15}215.vip-card .vc-level{font-size:13px;opacity:.9}216.vip-card .vc-name{font-size:20px;font-weight:800;margin-top:2px}217.vip-card .vc-exp{font-size:11px;opacity:.85;margin-top:4px}218.vip-card .vc-bar{height:6px;background:rgba(255,255,255,.25);border-radius:3px;margin-top:14px;position:relative}219.vip-card .vc-bar i{display:block;height:100%;width:68%;background:linear-gradient(90deg,#84cc16,#eab308);border-radius:3px}220.assets{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;padding:0 12px}221.asset-item{background:#fff;border-radius:12px;text-align:center;padding:14px 4px;box-shadow:0 1px 4px rgba(0,0,0,.05)}222.asset-item b{display:block;font-size:19px;color:var(--primary-dark)}223.asset-item span{font-size:11px;color:#9bbf93}224.sign-btn{background:linear-gradient(135deg,#ca8a04,#eab308);color:#fff;border-radius:20px;padding:11px;text-align:center;font-size:14px;font-weight:700;margin:12px;cursor:pointer}225.sign-btn.done{background:#d6e9cf;color:#7aa06d}226.vip-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:10px;padding:0 12px}227.vip-item{background:#fff;border-radius:12px;padding:14px;box-shadow:0 1px 4px rgba(0,0,0,.05)}228.vip-item .vi-emoji{font-size:26px}229.vip-item .vi-name{font-size:13px;font-weight:700;margin-top:4px}230.vip-item .vi-desc{font-size:10px;color:#9bbf93;margin-top:2px;line-height:1.5}231.recharge-box{background:#fff;border-radius:14px;margin:12px;padding:16px}232.recharge-box .rb-title{font-size:14px;font-weight:700;margin-bottom:10px}233.recharge-opts{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}234.recharge-opt{border:1px solid #cfe8c4;border-radius:10px;text-align:center;padding:10px 4px;font-size:12px}235.recharge-opt.sel{border-color:var(--primary);background:var(--primary-light);color:var(--primary-dark)}236.recharge-opt b{display:block;font-size:14px}237.recharge-opt span{color:#a8c2a0;font-size:10px}238.plan-box{background:#fff;border-radius:14px;margin:12px;padding:16px}239.plan-box .pb-title{font-size:14px;font-weight:700;margin-bottom:10px}240.plan-item{display:flex;align-items:center;gap:10px;padding:10px 0;border-bottom:1px solid #f0f7ec;font-size:13px}241.plan-item:last-child{border-bottom:none}242.plan-item .pi-day{width:80px;color:#2f6b28;flex-shrink:0}243.plan-item .pi-detail{flex:1;color:#3c5a35}244.plan-item .pi-switch{width:42px;height:24px;border-radius:12px;background:var(--primary);position:relative;flex-shrink:0}245.plan-item .pi-switch i{position:absolute;top:2px;right:2px;width:20px;height:20px;border-radius:50%;background:#fff}246.plan-item.off .pi-switch{background:#d6e9cf}247.plan-item.off .pi-switch i{right:auto;left:2px}248.credit-box{background:linear-gradient(135deg,#15803d,#16a34a);margin:12px;border-radius:14px;padding:16px;color:#fff;display:flex;align-items:center;gap:12px}249.credit-box .cb-left{flex:1}250.credit-box .cb-left b{font-size:18px;display:block}251.credit-box .cb-left span{font-size:11px;opacity:.9}252.credit-box .cb-btn{background:rgba(255,255,255,.22);color:#fff;padding:8px 14px;border-radius:16px;font-size:12px;font-weight:700}253/* 我的 */254.user-card{background:linear-gradient(135deg,#14532d,#16a34a);margin:12px;border-radius:14px;color:#fff;padding:18px;display:flex;align-items:center;gap:12px}255.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}256.user-card .uc-name{font-size:17px;font-weight:600}257.user-card .uc-level{font-size:12px;opacity:.9;margin-top:3px}258.order-entry{background:#fff;border-radius:12px;margin:12px;display:flex;padding:14px 0}259.order-entry a{flex:1;text-align:center;font-size:11px;color:#2f6b28}260.order-entry a .oe-ico{font-size:22px;display:block;margin-bottom:4px;position:relative}261.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}262.menu-list{background:#fff;border-radius:12px;margin:12px;overflow:hidden}263.menu-list a{display:flex;align-items:center;justify-content:space-between;padding:14px 16px;border-bottom:1px solid #f0f7ec;font-size:14px}264.menu-list a:last-child{border-bottom:none}265.menu-list a .ml-l{display:flex;align-items:center;gap:10px}266.menu-list a .ml-l .ico{font-size:20px}267.menu-list a .ml-r{color:#ccc;font-size:12px}268.empty{text-align:center;color:#a8c2a0;font-size:13px;padding:40px 0}269.empty .e-icon{font-size:44px;display:block;margin-bottom:8px}270"""271272DATA = """// 小草蔬菜批发配送 · 演示数据273window.DATA = {274 categories: ["时令蔬菜", "鲜果干货", "肉禽蛋品", "水产海鲜", "冷冻食品", "调味粮油"],275 units: ["斤", "箱(10斤)", "袋(5斤)", "份"],276 products: [277 { id: 1, img: "🥬", name: "山东寿光大白菜", cat: "时令蔬菜", price: 1.8, unit: "斤", old: 2.2, sales: 32000, origin: "山东寿光", grade: { retail: 1.8, wholesale: 1.5, vip: 1.3 }, tags: ["产地直供", "当日采摘"], desc: "山东寿光大棚大白菜,帮薄叶嫩水分足,适合食堂炖炒", hot: true, new: false },278 { id: 2, img: "🥔", name: "云南高原黄心土豆", cat: "时令蔬菜", price: 2.2, unit: "斤", old: 2.6, sales: 28000, origin: "云南", grade: { retail: 2.2, wholesale: 1.9, vip: 1.7 }, tags: ["高原种植", "粉糯"], desc: "云南高海拔黄心土豆,淀粉足口感粉糯,做薯条炖肉皆宜", hot: true, new: false },279 { id: 3, img: "🍅", name: "宁夏沙瓤番茄", cat: "时令蔬菜", price: 3.5, unit: "斤", old: 4.2, sales: 19000, origin: "宁夏", grade: { retail: 3.5, wholesale: 3.0, vip: 2.6 }, tags: ["沙瓤多汁"], desc: "宁夏日光番茄,沙瓤爆汁酸甜,凉拌炒菜都好吃", hot: false, new: false },280 { id: 4, img: "🥦", name: "浙江有机西兰花", cat: "时令蔬菜", price: 4.5, unit: "斤", old: 5.2, sales: 15000, origin: "浙江", grade: { retail: 4.5, wholesale: 3.9, vip: 3.5 }, tags: ["有机认证"], desc: "有机种植西兰花,花球紧实翠绿,减脂餐首选", hot: false, new: true },281 { id: 5, img: "🥒", name: "本地旱黄瓜", cat: "时令蔬菜", price: 2.5, unit: "斤", old: 3.0, sales: 21000, origin: "本地基地", grade: { retail: 2.5, wholesale: 2.1, vip: 1.9 }, tags: ["带刺新鲜"], desc: "本地大棚旱黄瓜,顶花带刺脆嫩清香,生吃也水灵", hot: false, new: false },282 { id: 6, img: "🍎", name: "栖霞红富士苹果", cat: "鲜果干货", price: 5.5, unit: "斤", old: 6.5, sales: 24000, origin: "山东栖霞", grade: { retail: 5.5, wholesale: 4.8, vip: 4.3 }, tags: ["脆甜多汁"], desc: "栖霞红富士,皮薄肉脆汁水丰,糖度高达 14 度", hot: true, new: false },283 { id: 7, img: "🍌", name: "菲律宾香蕉", cat: "鲜果干货", price: 3.2, unit: "斤", old: 3.8, sales: 17000, origin: "菲律宾", grade: { retail: 3.2, wholesale: 2.8, vip: 2.5 }, tags: ["即食软糯"], desc: "进口香蕉自然催熟,软糯香甜,餐厅果盘常备", hot: false, new: false },284 { id: 8, img: "🌾", name: "东北珍珠大米", cat: "调味粮油", price: 2.8, unit: "斤", old: 3.2, sales: 30000, origin: "黑龙江", grade: { retail: 2.8, wholesale: 2.4, vip: 2.1 }, tags: ["新米", "5kg装"], desc: "东北寒地珍珠米,粒粒饱满清香软糯,食堂主粮首选", hot: true, new: false },285 { id: 9, img: "🥚", name: "土鸡蛋(约10枚)", cat: "肉禽蛋品", price: 5.0, unit: "斤", old: 5.8, sales: 26000, origin: "散养基地", grade: { retail: 5.0, wholesale: 4.5, vip: 4.0 }, tags: ["散养土鸡", "新鲜"], desc: "林下散养土鸡蛋,蛋黄橙红浓香,早餐食堂刚需", hot: true, new: false },286 { id: 10, img: "🍗", name: "冰鲜鸡腿肉", cat: "肉禽蛋品", price: 9.0, unit: "斤", old: 10.5, sales: 13000, origin: "正大", grade: { retail: 9.0, wholesale: 8.2, vip: 7.6 }, tags: ["冷鲜", "无激素"], desc: "品牌冷鲜鸡腿,肉质细嫩无骨少脂,快餐爆品原料", hot: false, new: false },287 { id: 11, img: "🐟", name: "舟山带鱼", cat: "水产海鲜", price: 12.0, unit: "斤", old: 14.0, sales: 9000, origin: "舟山", grade: { retail: 12.0, wholesale: 10.5, vip: 9.5 }, tags: ["深海", "冰鲜"], desc: "舟山深海带鱼,银鳞完整肉质细,红烧干煎都鲜", hot: false, new: false },288 { id: 12, img: "🦐", name: "南美对虾", cat: "水产海鲜", price: 28.0, unit: "斤", old: 33.0, sales: 7000, origin: "湛江", grade: { retail: 28.0, wholesale: 25.0, vip: 23.0 }, tags: ["活冻", "个大"], desc: "湛江活冻对虾,个大饱满 Q 弹,宴席餐厅硬菜", hot: true, new: false },289 { id: 13, img: "❄️", name: "冷冻鸡块(裹粉)", cat: "冷冻食品", price: 7.5, unit: "斤", old: 8.8, sales: 11000, origin: "圣农", grade: { retail: 7.5, wholesale: 6.8, vip: 6.2 }, tags: ["半成品", "即炸"], desc: "裹粉鸡块半成品,解冻即炸出餐快,快餐小吃必备", hot: false, new: false },290 { id: 14, img: "🍢", name: "火锅牛肉丸", cat: "冷冻食品", price: 11.0, unit: "斤", old: 13.0, sales: 8500, origin: "潮汕", grade: { retail: 11.0, wholesale: 9.8, vip: 9.0 }, tags: ["手打", "弹牙"], desc: "潮汕手打牛肉丸,肉质紧实弹牙爆汁,火锅食材爆款", hot: false, new: true },291 { id: 15, img: "🧴", name: "零添加生抽", cat: "调味粮油", price: 6.0, unit: "瓶", old: 7.5, sales: 16000, origin: "海天", grade: { retail: 6.0, wholesale: 5.2, vip: 4.8 }, tags: ["餐饮装", "1.9L"], desc: "餐饮大装生抽,零添加酿造,餐厅后厨调味常备", hot: false, new: false }292 ],293 combos: [294 { img: "🥘", name: "火锅食材包", price: 88, old: 108, desc: "牛肉丸+带鱼+白菜+菌菇 4 样组合装" },295 { img: "🥗", name: "食堂凉菜包", price: 36, old: 45, desc: "黄瓜+番茄+西兰花 时蔬三拼" }296 ],297 seckills: [298 { img: "🥬", name: "大白菜", price: 0.99, old: 1.8 },299 { img: "🥔", name: "黄心土豆", price: 1.49, old: 2.2 },300 { img: "🍅", name: "沙瓤番茄", price: 2.49, old: 3.5 },301 { img: "🥒", name: "旱黄瓜", price: 1.69, old: 2.5 }302 ],303 priceNews: [304 { name: "山东大白菜", price: "1.8/斤", chg: "-8%", dir: "down" },305 { name: "宁夏番茄", price: "3.5/斤", chg: "+5%", dir: "up" },306 { name: "云南土豆", price: "2.2/斤", chg: "-3%", dir: "down" },307 { name: "南美对虾", price: "28/斤", chg: "+2%", dir: "up" }308 ],309 evals: [310 { avatar: "🍲", name: "老街食堂王老板", star: "★★★★★", text: "合作半年了,每天凌晨下单,早市前准时送到,菜品新鲜损耗低,账期月结资金压力小。" },311 { avatar: "🏨", name: "某连锁酒店采购", star: "★★★★★", text: "一客一价很省心,我们大客户协议价比零售便宜近三成,批量越大越划算。" },312 { avatar: "🥗", name: "轻食工作室", star: "★★★★☆", text: "西兰花有机认证溯源码齐全,客人吃得放心,就是旺季偶尔要等补货。" }313 ],314 coupons: [315 { name: "新商户立减券", val: "¥20", cond: "满 100 可用" },316 { name: "满减神券", val: "¥50", cond: "满 300 可用" },317 { name: "配送费券", val: "免运费", cond: "满 200 可用" }318 ],319 recharge: [320 { val: "500", gift: "送 30 元券" },321 { val: "1000", gift: "送 80 元券" },322 { val: "3000", gift: "送 300 元券" }323 ],324 stores: [325 { name: "城东农产品仓", dist: "2.3km", time: "00:00-22:00", addr: "物流园 A 区 12 号" },326 { name: "城南配送站", dist: "5.1km", time: "03:00-20:00", addr: "南三环仓储中心" }327 ],328 creditLevels: [329 { level: "青铜 · 零售", discount: "原价", credit: "¥0", note: "散客/小餐馆" },330 { level: "白银 · 小批发", discount: "95 折", credit: "¥2000", note: "周结 · 小餐饮" },331 { level: "黄金 · 大批发", discount: "9 折", credit: "¥10000", note: "月结 · 连锁" },332 { level: "钻石 · 战略合作", discount: "协商价", credit: "¥50000", note: "账期 · 大客户" }333 ],334 regularPlans: [335 { day: "每周一", detail: "大白菜 50 斤 + 土豆 30 斤", on: true },336 { day: "每周三", detail: "番茄 40 斤 + 西兰花 20 斤", on: true },337 { day: "每周五", detail: "鸡蛋 2 箱 + 大米 1 袋", on: false }338 ],339 orderStatus: [340 { title: "已接单 · 客服确认订单", time: "03:12", done: true },341 { title: "已分拣 · 仓内称重打包", time: "03:40", now: true },342 { title: "配送中 · 司机已出发", time: "预计 05:20", done: false },343 { title: "已签收 · 请确认收货", time: "待送达", done: false },344 { title: "已结算 · 账期自动对账", time: "", done: false }345 ]346};347"""348349APP = """// 小草蔬菜批发配送 · 交互逻辑350document.addEventListener('click', function (e) {351 var t = e.target.closest('[data-toast]');352 if (t) { toast(t.getAttribute('data-toast')); }353 var ct = e.target.closest('.cat-tab');354 if (ct) {355 var wrap = ct.parentElement;356 [].forEach.call(wrap.children, function (x) { x.classList.remove('sel'); });357 ct.classList.add('sel');358 var kw = ct.textContent;359 var cards = document.querySelectorAll('.veg-card');360 [].forEach.call(cards, function (c) {361 c.style.display = (kw === '全部' || c.getAttribute('data-cat') === kw) ? 'flex' : 'none';362 });363 }364 var so = e.target.closest('.sort-bar span');365 if (so) {366 var w2 = so.parentElement;367 [].forEach.call(w2.children, function (x) { x.classList.remove('on'); });368 so.classList.add('on');369 }370 var sp = e.target.closest('.spec-opt');371 if (sp) {372 var grp = sp.parentElement;373 [].forEach.call(grp.children, function (x) { x.classList.remove('sel'); });374 sp.classList.add('sel');375 }376 var sn = e.target.closest('.sr-num i');377 if (sn) {378 var b = sn.parentElement.querySelector('b');379 var v = parseInt(b.textContent) || 1;380 v = sn.textContent === '+' ? v + 1 : Math.max(1, v - 1);381 b.textContent = v;382 }383 var ci = e.target.closest('.ci-num i');384 if (ci) {385 var b = ci.parentElement.querySelector('b');386 var v = parseInt(b.textContent) || 1;387 v = ci.textContent === '+' ? v + 1 : Math.max(1, v - 1);388 b.textContent = v;389 }390 var ck = e.target.closest('.ci-check');391 if (ck) { ck.parentElement.classList.toggle('checked'); }392 var opt = e.target.closest('.cb-val .opt');393 if (opt) {394 var grp = opt.parentElement;395 [].forEach.call(grp.children, function (x) { x.classList.remove('sel'); });396 opt.classList.add('sel');397 }398 var pw = e.target.closest('.pw-item');399 if (pw) {400 var box = pw.parentElement;401 [].forEach.call(box.children, function (x) { x.classList.remove('sel'); });402 pw.classList.add('sel');403 }404 var sg = e.target.closest('.sign-btn');405 if (sg && !sg.classList.contains('done')) { sg.classList.add('done'); sg.textContent = '今日已签到 +10 积分'; toast('签到成功,积分 +10'); }406 var rg = e.target.closest('.recharge-opt');407 if (rg) {408 var grp = rg.parentElement;409 [].forEach.call(grp.children, function (x) { x.classList.remove('sel'); });410 rg.classList.add('sel');411 }412 var cp = e.target.closest('.cc-btn');413 if (cp) { cp.textContent = '已领取'; cp.style.opacity = '.6'; toast('优惠券已到账'); }414 var pl = e.target.closest('.pi-switch');415 if (pl) { pl.parentElement.classList.toggle('off'); }416});417// 秒杀倒计时418(function () {419 var box = document.querySelector('.sk-time');420 if (!box) return;421 var total = 2 * 3600 + 12 * 60 + 40;422 setInterval(function () {423 total--;424 if (total < 0) total = 86399;425 var h = Math.floor(total / 3600), m = Math.floor(total % 3600 / 60), s = total % 60;426 var z = function (n) { return n < 10 ? '0' + n : '' + n; };427 box.innerHTML = '<i>' + z(h) + '</i>:<i>' + z(m) + '</i>:<i>' + z(s) + '</i>';428 }, 1000);429})();430function toast(msg) {431 var d = document.createElement('div');432 d.style.cssText = 'position:fixed;left:50%;bottom:110px;transform:translateX(-50%);background:rgba(20,83,45,.92);color:#fff;padding:10px 20px;border-radius:20px;font-size:13px;z-index:999';433 d.textContent = msg;434 document.body.appendChild(d);435 setTimeout(function () { d.remove(); }, 1800);436}437"""438439def page(title, active, body, tabbar):440 # 把 body 中的内联渲染脚本(依赖 window.DATA)提取出来,放到 data.js 之后执行,441 # 否则脚本在 data.js 加载前运行会因 window.DATA 未定义而渲染失败(列表为空)。442 inline_scripts = re.findall(r'<script>(.*?)</script>', body, re.S)443 body_clean = re.sub(r'<script>.*?</script>', '', body, flags=re.S)444 inline_html = "".join("<script>" + s + "</script>" for s in inline_scripts)445 return """<!DOCTYPE html>446<html lang="zh-CN">447<head>448<meta charset="UTF-8"/>449<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"/>450<title>""" + title + """</title>451<link rel="stylesheet" href="style.css"/>452</head>453<body>454""" + body_clean + """455""" + tabbar + """456<script src="data.js"></script>457""" + inline_html + """458<script src="app.js"></script>459</body>460</html>"""461462def tabbar(active):463 items = [464 ("index.html", "🏠", "首页"),465 ("category.html", "🛒", "采购"),466 ("cart.html", "📋", "进货单"),467 ("member.html", "👑", "客户"),468 ("mine.html", "👤", "我的"),469 ]470 h = '<nav class="tabbar">'471 for href, icon, name in items:472 cls = ' active' if name == active else ''473 h += '<a class="' + cls + '" href="' + href + '"><span class="icon">' + icon + '</span>' + name + '</a>'474 return h + '</nav>'475476def header(title, back=True, right=""):477 b = '<a class="back" onclick="history.back()">‹</a>' if back else '<span class="back"></span>'478 return '<header class="header">' + b + '<h1>' + title + '</h1><span class="right">' + right + '</span></header>'479480INDEX = """481<div class="banner">482 <div>483 <div class="bn-title">某杰蔬菜批发配送</div>484 <div class="bn-sub">产地直供 · 一件起批 · 凌晨下单早市达<br/>餐饮/食堂/商超一站式食材采购 · 支持账期</div>485 <div class="bn-badge">🎁 新商户首单立减 20 元</div>486 </div>487 <div class="bn-emoji">🥬</div>488</div>489<div class="search-box" data-toast="拍照找菜:上传菜品图自动匹配">490 <span class="s-ico">🔍</span>491 <input placeholder="搜索蔬菜 / 水果 / 肉禽 / 水产…"/>492 <span class="s-btn">搜索</span>493</div>494<div class="cat-grid">495 <a href="category.html"><span class="c-emoji">🥬</span><span class="c-name">时令蔬菜</span></a>496 <a href="category.html"><span class="c-emoji">🍎</span><span class="c-name">鲜果干货</span></a>497 <a href="category.html"><span class="c-emoji">🍗</span><span class="c-name">肉禽蛋品</span></a>498 <a href="category.html"><span class="c-emoji">🐟</span><span class="c-name">水产海鲜</span></a>499 <a href="category.html"><span class="c-emoji">❄️</span><span class="c-name">冷冻食品</span></a>500 <a href="category.html"><span class="c-emoji">🧴</span><span class="c-name">调味粮油</span></a>501</div>502<div class="quick-grid">503 <a href="category.html"><div class="qicon">📦</div>批量采购</a>504 <a data-toast="已为你开启每周固定订货"><div class="qicon">🔁</div>定期配送</a>505 <a href="member.html"><div class="qicon">🪪</div>客户等级</a>506 <a href="cart.html"><div class="qicon">📋</div>进货单</a>507 <a data-toast="邀请同行各得 20 元券"><div class="qicon">🤝</div>邀请同行</a>508</div>509<div class="price-news">510 <div class="pn-head">📈 今日产地行情 <span class="pn-tag">实时更新</span></div>511 <div id="priceList"></div>512</div>513<div class="seckill">514 <div class="sk-head"><b>⚡ 限时秒杀 · 产地清仓</b><div class="sk-time"><i>02</i>:<i>12</i>:<i>40</i></div></div>515 <div class="sk-body" id="skList"></div>516</div>517<div class="coupon-card" style="background:linear-gradient(135deg,#15803d,#16a34a);margin:12px;border-radius:14px;padding:14px;display:flex;align-items:center;gap:12px;color:#fff">518 <div style="flex:1"><b style="font-size:18px;display:block">新商户立减 20 元无门槛券</b><span style="font-size:11px;opacity:.9">B 端专用 · 30 天内有效</span></div>519 <div class="cc-btn" data-toast="优惠券已到账" style="background:#fff;color:#15803d;padding:8px 16px;border-radius:16px;font-size:12px;font-weight:700">立即领取</div>520</div>521<div class="section-title">🔥 产地直供爆品 <span>月供 30 万+</span></div>522<div class="veg-card" data-toast="已加入进货单">523 <div class="vc-img">🥬</div>524 <div class="vc-body">525 <div class="vc-name">山东寿光大白菜 <span class="badge badge-org">产地直供</span></div>526 <div class="vc-desc">大棚大白菜,帮薄叶嫩水分足,食堂炖炒必备</div>527 <div class="vc-meta">月供 3.2 万斤 · 山东寿光</div>528 <div class="vc-foot"><div class="vc-price">¥1.8<small> /斤 原2.2</small></div><div class="vc-add">+</div></div>529 </div>530</div>531<div class="section-title">🥘 组合食材包</div>532<div id="comboList"></div>533<div class="section-title">🏪 就近配送仓</div>534<div id="storeList"></div>535<script>536 var pl = document.getElementById('priceList');537 var h0 = '';538 window.DATA.priceNews.forEach(function (x) {539 h0 += '<div class="pn-item"><span class="pn-name">' + x.name + '</span><span class="pn-price">' + x.price + '</span>'540 + '<span class="pn-chg ' + x.dir + '">' + x.chg + '</span></div>';541 });542 pl.innerHTML = h0;543 var sk = document.getElementById('skList');544 var h = '';545 window.DATA.seckills.forEach(function (x) {546 h += '<div class="sk-item"><div class="sk-img">' + x.img + '</div><div class="sk-name">' + x.name + '</div>'547 + '<div class="sk-price">¥' + x.price + '</div><div class="sk-old">¥' + x.old + '</div></div>';548 });549 sk.innerHTML = h;550 var cl = document.getElementById('comboList');551 var h2 = '';552 window.DATA.combos.forEach(function (c) {553 h2 += '<div class="veg-card"><div class="vc-img">' + c.img + '</div><div class="vc-body">'554 + '<div class="vc-name">' + c.name + ' <span class="badge badge-sale">组合</span></div>'555 + '<div class="vc-desc">' + c.desc + '</div>'556 + '<div class="vc-foot"><div class="vc-price">¥' + c.price + '<small> /原' + c.old + '</small></div>'557 + '<div class="vc-add" data-toast="组合已加入进货单">+</div></div></div></div>';558 });559 cl.innerHTML = h2;560 var sl = document.getElementById('storeList');561 var h3 = '';562 window.DATA.stores.slice(0, 2).forEach(function (s) {563 h3 += '<div class="veg-card"><div class="vc-img">🏪</div><div class="vc-body">'564 + '<div class="vc-name">' + s.name + ' <span class="tag">' + s.dist + '</span></div>'565 + '<div class="vc-desc">' + s.addr + ' · 营业 ' + s.time + '</div>'566 + '<div class="vc-foot"><div class="vc-add" data-toast="已选择该配送仓" style="width:auto;height:auto;border-radius:14px;padding:6px 14px;font-size:12px">选仓</div></div></div></div>';567 });568 sl.innerHTML = h3;569</script>570"""571572CATEGORY = """573""" + header("采购下单", back=False, right="🔍") + """574<div class="cat-tabs"></div>575<div class="sort-bar"><span class="on">综合排序</span><span>销量优先</span><span>价格从低到高</span></div>576<div id="catList"></div>577<div class="cart-float">578 <div class="cf-cart"><span class="ico">📋<span class="num">5</span></span>进货单</div>579 <div class="cf-total"><b>¥168</b></div>580 <div class="cf-btn" data-toast="已跳转进货单">去进货单</div>581</div>582<script>583 var ctw = document.querySelector('.cat-tabs');584 var h0 = '<div class="cat-tab sel">全部</div>';585 window.DATA.categories.forEach(function (c) {586 h0 += '<div class="cat-tab">' + c + '</div>';587 });588 ctw.innerHTML = h0;589 var cl = document.getElementById('catList');590 var h = '';591 window.DATA.products.forEach(function (b) {592 h += '<div class="veg-card" data-cat="' + b.cat + '"><div class="vc-img">' + b.img + '</div><div class="vc-body">'593 + '<div class="vc-name">' + b.name + (b.hot ? ' <span class="badge badge-hot">热供</span>' : '') + (b.new ? ' <span class="badge badge-new">新品</span>' : '') + '</div>'594 + '<div class="vc-desc">' + b.desc + '</div>'595 + '<div class="vc-meta">月供 ' + b.sales.toLocaleString() + '斤+ · ' + b.origin + ' · ' + b.tags.join('/') + '</div>'596 + '<div class="vc-foot"><div class="vc-price">¥' + b.price + '<small> /' + b.unit + (b.old ? ' 原' + b.old : '') + '</small></div>'597 + '<div class="vc-add" data-toast="已加入进货单">+</div></div></div></div>';598 });599 cl.innerHTML = h;600</script>601"""602603DETAIL = """604""" + header("商品详情") + """605<div class="detail-img"><div class="di-badge">📷 产地实拍 · 检测报告</div>🥬</div>606<div class="detail-price">607 <div class="dp-num">¥1.8<small> /斤</small> <span style="color:#dc2626;font-size:13px">大客户 ¥1.3 起</span></div>608 <div class="dp-meta">山东寿光大白菜 · 当日采摘 · 产地直供 · 带溯源码 · 食堂餐饮商超均可</div>609 <div class="dp-row">610 <div class="dp-cell">🏷️ 月供 3.2 万斤</div>611 <div class="dp-cell">📍 山东寿光</div>612 <div class="dp-cell">✅ 检测合格</div>613 <div class="dp-cell">🚚 早市达</div>614 </div>615</div>616<div class="tier-box">617 <div class="tb-title">💎 一客一价 · 您的等级价</div>618 <div class="tier-row"><span class="tr-label">零售价</span><span class="tr-price">¥<b>1.8</b>/斤</span></div>619 <div class="tier-row"><span class="tr-label">批发价</span><span class="tr-price">¥<b>1.5</b>/斤</span></div>620 <div class="tier-row cur"><span class="tr-label">大客户协议价</span><span class="tr-price">¥<b>1.3</b>/斤</span></div>621 <div style="text-align:right;font-size:11px;color:#9bbf93;margin-top:8px">采购量越大越优惠 · 当前显示黄金会员价</div>622</div>623<div class="spec-box">624 <div class="sb-title">选择规格</div>625 <div class="spec-row"><span class="sr-label">包装</span><div class="sr-opts"><div class="spec-opt sel">散装(斤)</div><div class="spec-opt">箱装 10 斤</div><div class="spec-opt">袋装 5 斤</div></div></div>626 <div class="spec-row"><span class="sr-label">品级</span><div class="sr-opts"><div class="spec-opt sel">一级</div><div class="spec-opt">二级(惠)</div></div></div>627 <div class="spec-row"><span class="sr-label">数量</span><div class="sr-num"><i>-</i><b>10</b><i>+</i></div></div>628</div>629<div class="section-title">📋 关于这批菜</div>630<div class="card" style="margin-top:0;font-size:12px;color:#3c5a35;line-height:2">631 产地:山东寿光核心产区,合作社直采不倒手<br/>632 品控:每批附农残检测报告 + 产地溯源码,扫码可查<br/>633 新鲜度:当日凌晨采摘,冷链直发,到仓不超过 12 小时<br/>634 规格:散装按斤、箱装/袋装大包装更优惠,详情看定价635</div>636<div class="section-title">💬 采购商评价(1280+)</div>637<div id="evalList"></div>638<div class="section-title">❤️ 猜你需要</div>639<div id="guessList" style="display:flex;gap:10px;overflow-x:auto;padding:0 12px;scrollbar-width:none"></div>640<div style="height:70px"></div>641<div class="buy-bar">642 <div class="bb-cart"><span class="ico">📋<span class="num">5</span></span>进货单</div>643 <div class="bb-btn buy" data-toast="已加入进货单">加入进货单</div>644 <div class="bb-btn now" data-toast="订单提交成功">立即下单</div>645</div>646<script>647 var el = document.getElementById('evalList');648 var h = '';649 window.DATA.evals.forEach(function (x) {650 h += '<div class="eval-card"><div class="ev-head"><div class="ev-avatar">' + x.avatar + '</div>'651 + '<div>' + x.name + '</div><div class="ev-star">' + x.star + '</div>'652 + '</div><div class="ev-text">' + x.text + '</div></div>';653 });654 el.innerHTML = h;655 var gl = document.getElementById('guessList');656 var h2 = '';657 window.DATA.products.slice(1, 5).forEach(function (b) {658 h2 += '<div class="sk-item" style="width:110px"><div class="sk-img" style="height:80px">' + b.img + '</div>'659 + '<div class="sk-name">' + b.name + '</div><div class="sk-price">¥' + b.price + '</div></div>';660 });661 gl.innerHTML = h2;662</script>663"""664665CART = """666""" + header("进货单") + """667<div class="cart-item checked">668 <div class="ci-check">✓</div>669 <div class="ci-img">🥬</div>670 <div class="ci-body">671 <div class="ci-name">山东寿光大白菜 <span class="badge badge-org">直供</span></div>672 <div class="ci-spec">散装 · 一级 · 批发价</div>673 <div class="ci-foot"><div class="ci-price">¥1.5/斤</div><div class="ci-num"><i>-</i><b>50</b><i>+</i></div></div>674 </div>675</div>676<div class="cart-item checked">677 <div class="ci-check">✓</div>678 <div class="ci-img">🥔</div>679 <div class="ci-body">680 <div class="ci-name">云南黄心土豆</div>681 <div class="ci-spec">散装 · 一级 · 批发价</div>682 <div class="ci-foot"><div class="ci-price">¥1.9/斤</div><div class="ci-num"><i>-</i><b>30</b><i>+</i></div></div>683 </div>684</div>685<div class="cart-item">686 <div class="ci-check"></div>687 <div class="ci-img">🍅</div>688 <div class="ci-body">689 <div class="ci-name">宁夏沙瓤番茄 <span class="badge badge-new">热供</span></div>690 <div class="ci-spec">散装 · 一级 · 批发价</div>691 <div class="ci-foot"><div class="ci-price">¥3.0/斤</div><div class="ci-num"><i>-</i><b>20</b><i>+</i></div></div>692 </div>693</div>694<div class="coupon-card" style="margin-top:12px;background:linear-gradient(135deg,#15803d,#16a34a);border-radius:14px;padding:14px;display:flex;align-items:center;gap:12px;color:#fff">695 <div style="flex:1"><b style="font-size:18px;display:block">满 300 减 50 神券</b><span style="font-size:11px;opacity:.9">进货单金额 231 元 · 还差 69 元可用</span></div>696 <div class="cc-btn" data-toast="再凑 69 元即可用券" style="background:#fff;color:#15803d;padding:8px 16px;border-radius:16px;font-size:12px;font-weight:700">去凑单</div>697</div>698<div class="check-box">699 <div class="cb-row"><span class="cb-label">配送仓</span><span class="cb-val">城东农产品仓 <span class="tag">2.3km</span></span></div>700 <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>701 <div class="cb-row"><span class="cb-label">配送方式</span><span class="cb-val"><span class="opt sel">🚚 送货上门</span><span class="opt">🏪 到仓自提</span></span></div>702 <div class="cb-row"><span class="cb-label">预约时间</span><span class="cb-val dim">明日 05:00 前达 ›</span></div>703 <div class="cb-row"><span class="cb-label">订单备注</span><span class="cb-val dim">带筐 / 不要黄叶 ›</span></div>704</div>705<div style="height:80px"></div>706<div class="settle-bar">707 <div class="sb-all"><span class="ci-check">✓</span>全选</div>708 <div class="sb-total">合计 <b>¥231</b><br/>已含运费</div>709 <div class="sb-btn" data-toast="已跳转结算">去结算</div>710</div>711"""712713ORDER = """714""" + header("确认订单") + """715<div class="pay-card">716 <div class="pc-row"><span class="pc-label">配送仓</span><span class="pc-val">城东农产品仓 · 物流园 A 区 12 号 ›</span></div>717 <div class="pc-row"><span class="pc-label">配送时段</span><span class="pc-val">🌅 凌晨达 · 明日 05:00 前</span></div>718 <div class="pc-row"><span class="pc-label">配送方式</span><span class="pc-val">🚚 送货上门(满 200 免运费)</span></div>719 <div class="pc-row"><span class="pc-label">订单备注</span><span class="pc-val dim">带筐 / 不要黄叶 ›</span></div>720</div>721<div class="card" style="margin-top:-4px">722 <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">山东寿光大白菜 ×50 斤</div><div style="font-size:12px;color:#9bbf93">¥75</div></div>723 <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">云南黄心土豆 ×30 斤</div><div style="font-size:12px;color:#9bbf93">¥57</div></div>724 <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">宁夏沙瓤番茄 ×20 斤</div><div style="font-size:12px;color:#9bbf93">¥60</div></div>725</div>726<div class="pay-card" style="margin-top:-4px">727 <div class="pc-row"><span class="pc-label">客户等级</span><span class="pc-val">黄金会员 · 9 折已享</span></div>728 <div class="pc-row"><span class="pc-label">优惠券</span><span class="pc-val" style="color:#dc2626">¥50 满减券 ▾</span></div>729 <div class="pc-row"><span class="pc-label">账期</span><span class="pc-val" style="color:#16a34a">月结 · 本月 30 日还款</span></div>730 <div class="pc-row"><span class="pc-label">实付金额</span><span class="pc-val"><b style="font-size:20px;color:var(--red)">¥158.3</b></span></div>731</div>732<div class="pay-way">733 <div class="pw-title">选择结算方式</div>734 <div class="pw-item sel"><span class="pw-ico">📅</span>账期月结(授信 ¥10000)<div class="pw-radio">✓</div></div>735 <div class="pw-item"><span class="pw-ico">💳</span>预存余额(¥5200)<div class="pw-radio"></div></div>736 <div class="pw-item"><span class="pw-ico">💚</span>微信支付<div class="pw-radio"></div></div>737 <div class="pw-item"><span class="pw-ico">💙</span>支付宝<div class="pw-radio"></div></div>738</div>739<div style="height:80px"></div>740<div class="settle-bar">741 <div class="sb-total" style="text-align:left">应付 <b>¥158.3</b></div>742 <div class="sb-btn" data-toast="下单成功,已转后台分拣">提交订单 ¥158.3</div>743</div>744"""745746ORDERS = """747""" + header("配送订单") + """748<div class="order-tabs">749 <a class="active">进行中</a><a>配送中</a><a>已完成</a>750</div>751<div class="track-bar">752 <div class="tb-ico">🚚</div>753 <div class="tb-body"><b>司机 张师傅 已出发</b><span>车牌 陕A·8F2X · 预计 05:20 送达城东仓</span></div>754 <div class="tb-btn" data-toast="已查看实时轨迹">查看轨迹</div>755</div>756<div class="order-card">757 <div class="oc-head"><span>城东仓 · 2026-09-09 03:12 <span class="tag">单号 CG202609090312</span></span><span class="st">配送中</span></div>758 <div class="oc-goods"><div class="og-img">🥬</div><div class="og-name">山东寿光大白菜 ×50 斤<br/><span style="font-size:11px;color:#9bbf93">散装 · 一级 · 批发价</span></div><div class="og-price">¥75</div></div>759 <div class="oc-goods"><div class="og-img">🥔</div><div class="og-name">云南黄心土豆 ×30 斤</div><div class="og-price">¥57</div></div>760 <div class="oc-foot"><span>共 3 种 · 实付</span><b>¥192</b></div>761 <div class="call-bar">762 <i data-toast="已发起缺货替代">🔄 缺货替代</i>763 <i data-toast="已催单">📞 催单</i>764 <i class="main" data-toast="已通知司机拍照签收">📷 签收拍照</i>765 </div>766</div>767<div class="section-title">📡 订单实时进度</div>768<div class="status-line" id="statusList"></div>769<div class="order-card" style="margin-top:12px">770 <div class="oc-head"><span>城东仓 · 2026-09-08 04:05</span><span class="st" style="color:#16a34a">已结算</span></div>771 <div class="oc-goods"><div class="og-img">🍎</div><div class="og-name">栖霞红富士 ×40 斤<br/><span style="font-size:11px;color:#9bbf93">箱装 · 一级</span></div><div class="og-price">¥192</div></div>772 <div class="oc-foot"><span>共 1 种 · 实付</span><b>¥192</b></div>773 <div class="oc-ops"><i class="main">去评价</i><i>再次采购</i></div>774</div>775<script>776 var sl = document.getElementById('statusList');777 var h = '';778 window.DATA.orderStatus.forEach(function (t) {779 var cls = t.now ? 'now' : (t.done ? 'done' : '');780 h += '<div class="sl-dot ' + cls + '"><div class="sl-c"></div><div>'781 + '<div class="sl-title">' + t.title + '</div><div class="sl-time">' + (t.time || '待处理') + '</div></div></div>';782 });783 sl.innerHTML = h;784</script>785"""786787MEMBER = """788""" + header("客户中心", back=False, right="⚙️") + """789<div class="vip-card">790 <div class="vc-level">👑 黄金会员 · 尊享 9 折</div>791 <div class="vc-name">某杰·黄金客户</div>792 <div class="vc-exp">距离钻石会员还差 38 成长值 · 授信额度 ¥10000</div>793 <div class="vc-bar"><i></i></div>794</div>795<div class="credit-box">796 <div class="cb-left"><b>可用授信 ¥10000</b><span>本月已用 ¥4200 · 30 日还款</span></div>797 <div class="cb-btn" data-toast="账期对账单已生成">查看对账</div>798</div>799<div class="assets">800 <div class="asset-item"><b>860</b><span>积分</span></div>801 <div class="asset-item"><b>¥5200</b><span>预存余额</span></div>802 <div class="asset-item"><b>3 张</b><span>优惠券</span></div>803</div>804<div class="sign-btn">📅 每日签到 +10 积分</div>805<div class="section-title">🪪 客户等级与权益</div>806<div class="recharge-box">807 <div class="rb-title">一客一价 · 等级越高价越低</div>808 <div id="creditList"></div>809</div>810<div class="section-title">🔁 定期配送计划</div>811<div class="plan-box">812 <div class="pb-title">到点自动生成采购单,无需每天重复下单</div>813 <div id="planList"></div>814</div>815<div class="section-title">💎 预存有礼</div>816<div class="recharge-box">817 <div class="rb-title">预存多充多赠 · 全渠道通用</div>818 <div class="recharge-opts">819 <div class="recharge-opt sel"><b>¥500</b><span>送 30 元券</span></div>820 <div class="recharge-opt"><b>¥1000</b><span>送 80 元券</span></div>821 <div class="recharge-opt"><b>¥3000</b><span>送 300 元券</span></div>822 </div>823 <div class="btn btn-gold" style="margin-top:14px" data-toast="充值成功,券已到账">立即预存</div>824</div>825<div class="section-title">🚀 拼单与活动</div>826<div class="vip-grid">827 <div class="vip-item" data-toast="已发起附近商户拼单"><div class="vi-emoji">👥</div><div class="vi-name">邻近拼单</div><div class="vi-desc">合并需求降物流成本</div></div>828 <div class="vip-item" data-toast="社区集采价已开启"><div class="vi-emoji">🏘️</div><div class="vi-name">社区集采</div><div class="vi-desc">集采享专属批发价</div></div>829 <div class="vip-item" data-toast="邀请同行得 20 元"><div class="vi-emoji">🤝</div><div class="vi-name">邀请返利</div><div class="vi-desc">同行下单返 5%</div></div>830 <div class="vip-item" data-toast="霸王餐抽奖已开启"><div class="vi-emoji">🎁</div><div class="vi-name">抽奖送菜</div><div class="vi-desc">每日抽免费菜券</div></div>831</div>832<script>833 var cl = document.getElementById('creditList');834 var h = '';835 window.DATA.creditLevels.forEach(function (c) {836 h += '<div class="tier-row"><span class="tr-label">' + c.level + '</span><span class="tr-price" style="flex:1;text-align:right">' + c.discount + ' · 授信 ' + c.credit + '<br/><span style="font-size:10px;color:#9bbf93;font-weight:400">' + c.note + '</span></span></div>';837 });838 cl.innerHTML = h;839 var pl = document.getElementById('planList');840 var h2 = '';841 window.DATA.regularPlans.forEach(function (p) {842 h2 += '<div class="plan-item' + (p.on ? '' : ' off') + '"><div class="pi-day">' + p.day + '</div><div class="pi-detail">' + p.detail + '</div><div class="pi-switch"><i></i></div></div>';843 });844 pl.innerHTML = h2;845</script>846"""847848MINE = """849<div class="user-card">850 <div class="uc-avatar">🧑🌾</div>851 <div>852 <div class="uc-name">某杰·黄金客户</div>853 <div class="uc-level">👑 黄金会员 · 成长值 1962 · 累计省 ¥2860</div>854 </div>855</div>856<div class="order-entry">857 <a data-toast="1 单配送中"><span class="oe-ico">🚚</span>配送中<span class="oe-num">1</span></a>858 <a data-toast="暂无待付款"><span class="oe-ico">💰</span>待付款</a>859 <a data-toast="1 单待签收"><span class="oe-ico">📦</span>待签收<span class="oe-num">1</span></a>860 <a data-toast="1 单待评价"><span class="oe-ico">⭐</span>待评价<span class="oe-num">1</span></a>861 <a data-toast="无退款"><span class="oe-ico">↩️</span>退款</a>862</div>863<div class="menu-list">864 <a href="orders.html"><span class="ml-l"><span class="ico">🧾</span>我的订单</span><span class="ml-r">›</span></a>865 <a href="member.html"><span class="ml-l"><span class="ico">👑</span>客户中心</span><span class="ml-r">›</span></a>866 <a data-toast="授信额度 ¥10000"><span class="ml-l"><span class="ico">🪪</span>我的授信</span><span class="ml-r">¥10000</span></a>867 <a data-toast="预存余额 ¥5200"><span class="ml-l"><span class="ico">💳</span>预存余额</span><span class="ml-r">¥5200</span></a>868 <a data-toast="积分 860"><span class="ml-l"><span class="ico">⭐</span>我的积分</span><span class="ml-r">860</span></a>869 <a data-toast="优惠券 3 张可用"><span class="ml-l"><span class="ico">🎟️</span>优惠券</span><span class="ml-r">3 张</span></a>870 <a data-toast="配送地址 2 个仓库"><span class="ml-l"><span class="ico">📍</span>配送地址</span><span class="ml-r">2 个</span></a>871 <a data-toast="收藏 12 款食材"><span class="ml-l"><span class="ico">❤️</span>我的收藏</span><span class="ml-r">12</span></a>872 <a data-toast="邀请同行各得 20 元券"><span class="ml-l"><span class="ico">🤝</span>邀请有礼</span><span class="ml-r">›</span></a>873 <a data-toast="客服在线 00:00-22:00"><span class="ml-l"><span class="ico">🎧</span>联系客服</span><span class="ml-r">400-666-2288</span></a>874</div>875"""876877README = """# 小草蔬菜批发配送(移动端 H5)878879蔬菜批发与同城配送 B2B 一体平台,功能对标美菜 / 美团快驴 / 望家欢等头部食材供应链系统,纯原生零依赖,移动端优先(390×844)。880881## 页面(8 页)882- index.html 首页:品牌 Banner、搜索/拍照找菜、六大分类导航、快捷入口(批量采购/定期配送/客户等级/进货单/邀请)、今日产地行情、限时秒杀、新客领券、产地直供爆品、组合食材包、就近配送仓883- category.html 采购:六大分类切换(时令蔬菜/鲜果干货/肉禽蛋品/水产海鲜/冷冻食品/调味粮油)、综合/销量/价格排序、食材卡(图/名/价/月供/产地/标签/加购)、底部进货单浮条884- detail.html 商品详情:一客一价三级定价表(零售/批发/大客户协议价)、包装/品级规格、数量步进、产地溯源与检测、采购商评价、猜你需要、加入进货单/立即下单885- cart.html 进货单:多商品勾选、数量调整、满减券凑单提示、配送仓/时段/方式、预约时间、备注、全选结算886- order.html 确认订单:配送信息确认、商品清单、客户等级折扣+满减券+账期、实付金额、结算方式(账期月结/预存/微信/支付宝)、提交订单887- orders.html 配送订单:进行中/配送中/已完成 Tab、实时配送轨迹、订单卡(单号/缺货替代/催单/签收拍照)、实时进度时间线(已接单→已分拣→配送中→已签收→已结算)888- member.html 客户中心:会员等级卡(成长值)、授信账期、积分/预存/券资产、每日签到、客户等级权益(一客一价)、定期配送计划、预存多充多赠、拼单/集采/邀请返利/抽奖889- mine.html 个人中心:客户卡、订单快捷入口(配送中/待付款/待签收/评价/退款)、授信/余额/积分/优惠券/配送地址/收藏/邀请有礼/客服890891## 文件892- style.css 移动端优先样式(蔬菜绿主题)893- app.js 零依赖交互逻辑(秒杀倒计时/分类筛选/规格选择/数量步进/签到/领券/账期选择/定期计划开关/Toast)894- data.js 演示数据集中管理(商品/套餐/秒杀/行情/评价/优惠券/预存档位/配送仓/客户等级/定期计划/订单状态)895"""896897def main():898 files = {899 "index.html": page("首页 · 某杰蔬菜批发配送", "index", INDEX, tabbar("首页")),900 "category.html": page("采购下单 · 某杰蔬菜", "category", CATEGORY, tabbar("采购")),901 "detail.html": page("商品详情 · 某杰蔬菜", "detail", DETAIL, tabbar("采购")),902 "cart.html": page("进货单 · 某杰蔬菜", "cart", CART, tabbar("进货单")),903 "order.html": page("确认订单 · 某杰蔬菜", "order", ORDER, tabbar("我的")),904 "orders.html": page("配送订单 · 某杰蔬菜", "orders", ORDERS, tabbar("我的")),905 "member.html": page("客户中心 · 某杰蔬菜", "member", MEMBER, tabbar("客户")),906 "mine.html": page("个人中心 · 某杰蔬菜", "mine", MINE, tabbar("我的")),907 "style.css": CSS,908 "data.js": DATA,909 "app.js": APP,910 "README.md": README,911 }912 for name, content in files.items():913 with open(os.path.join(OUT, name), "w", encoding="utf-8") as f:914 f.write(content)915 print(" +", name)916917if __name__ == "__main__":918 main()919