fresh-mint-pl-plan-load-delivery-split-demo.html 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796
  1. <!doctype html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <title>运输计划 · 装货左 / 送货右 分栏 Demo</title>
  7. <link rel="preconnect" href="https://fonts.googleapis.com" />
  8. <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
  9. <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
  10. <style>
  11. :root {
  12. --primary: #10b981;
  13. --primary-dark: #059669;
  14. --primary-bg: #ecfdf5;
  15. --text: #1e293b;
  16. --text-muted: #64748b;
  17. --border: #d9e8e2;
  18. --surface: #ffffff;
  19. --table-head: #f8fafc;
  20. --row-alt: #fafafa;
  21. --bg-page: #f1f5f9;
  22. --shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
  23. --shadow-lg: 0 12px 40px rgba(15, 23, 42, 0.14);
  24. --radius: 10px;
  25. --warn: #d97706;
  26. --warn-bg: #fffbeb;
  27. --danger: #dc2626;
  28. --info: #0284c7;
  29. --info-bg: #f0f9ff;
  30. --delivery-accent: #0284c7;
  31. --delivery-bg: #f0f9ff;
  32. --dialog-max: 1280px;
  33. }
  34. * { box-sizing: border-box; }
  35. body {
  36. margin: 0;
  37. min-height: 100vh;
  38. font-family: Inter, -apple-system, BlinkMacSystemFont, sans-serif;
  39. font-size: 14px;
  40. line-height: 1.5;
  41. color: var(--text);
  42. background: var(--bg-page);
  43. }
  44. .page { max-width: 1440px; margin: 0 auto; padding: 24px 20px 80px; }
  45. .hero {
  46. background: linear-gradient(135deg, #ecfdf5 0%, #fff 50%, #f0f9ff 100%);
  47. border: 1px solid var(--border);
  48. border-radius: var(--radius);
  49. padding: 22px 24px;
  50. margin-bottom: 18px;
  51. box-shadow: var(--shadow);
  52. }
  53. .hero h1 { margin: 0 0 8px; font-size: 22px; font-weight: 700; }
  54. .hero h1 em { font-style: normal; color: var(--primary-dark); }
  55. .hero p { margin: 0; color: var(--text-muted); max-width: 980px; }
  56. .pills { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
  57. .pill {
  58. display: inline-flex; align-items: center; gap: 6px;
  59. padding: 4px 10px; border-radius: 999px; font-size: 12px; font-weight: 500;
  60. background: var(--primary-bg); color: var(--primary-dark); border: 1px solid #a7f3d0;
  61. }
  62. .pill.blue { background: var(--delivery-bg); color: var(--delivery-accent); border-color: #bae6fd; }
  63. .pill.muted { background: #f1f5f9; color: var(--text-muted); border-color: #e2e8f0; }
  64. .toolbar {
  65. display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
  66. background: #fff; border: 1px solid var(--border); border-radius: var(--radius);
  67. padding: 12px 14px; margin-bottom: 14px; box-shadow: var(--shadow);
  68. }
  69. .toolbar label { font-size: 12px; color: var(--text-muted); font-weight: 600; }
  70. .toolbar select {
  71. height: 34px; border: 1px solid var(--border); border-radius: 8px;
  72. padding: 0 10px; font: inherit;
  73. }
  74. .scheme-tabs {
  75. display: flex; flex-wrap: wrap; gap: 6px;
  76. background: #fff; border: 1px solid var(--border);
  77. border-radius: var(--radius) var(--radius) 0 0; padding: 10px 12px 0;
  78. }
  79. .scheme-tab {
  80. border: none; background: transparent; cursor: pointer;
  81. padding: 10px 14px; font-size: 13px; font-weight: 600;
  82. color: var(--text-muted); border-bottom: 2px solid transparent; font-family: inherit;
  83. }
  84. .scheme-tab.active { color: var(--primary-dark); border-bottom-color: var(--primary); }
  85. .scheme-tab.recommended::after {
  86. content: "推荐"; margin-left: 6px; font-size: 10px; font-weight: 700;
  87. color: #fff; background: var(--primary-dark); padding: 1px 6px; border-radius: 999px;
  88. }
  89. .scheme-panel {
  90. display: none; background: #fff; border: 1px solid var(--border); border-top: none;
  91. border-radius: 0 0 var(--radius) var(--radius); padding: 16px 18px 22px; box-shadow: var(--shadow);
  92. }
  93. .scheme-panel.active { display: block; }
  94. .scheme-desc {
  95. margin: 0 0 14px; padding: 10px 12px; border-radius: 8px; font-size: 12px;
  96. border: 1px solid #bae6fd; background: var(--info-bg); color: #0369a1;
  97. }
  98. .scheme-desc.ok { border-color: #a7f3d0; background: var(--primary-bg); color: var(--primary-dark); }
  99. /* 模拟弹窗 */
  100. .dialog-sim {
  101. width: var(--dialog-max); max-width: 100%; margin: 0 auto;
  102. border: 1px solid var(--border); border-radius: var(--radius);
  103. background: #fff; box-shadow: var(--shadow-lg); overflow: hidden;
  104. }
  105. .dialog-sim__hd {
  106. padding: 14px 18px; border-bottom: 1px solid var(--border);
  107. font-weight: 700; font-size: 15px;
  108. }
  109. .dialog-sim__bd { padding: 16px 18px 20px; background: #fafcfb; }
  110. .section { margin-bottom: 16px; }
  111. .section-title {
  112. margin: 0 0 10px; font-size: 14px; font-weight: 700;
  113. display: flex; align-items: center; justify-content: space-between; gap: 12px;
  114. }
  115. .section-title span:first-child { display: flex; align-items: center; gap: 8px; }
  116. .section-title span:first-child::before {
  117. content: ""; width: 3px; height: 14px; border-radius: 2px; background: var(--primary);
  118. }
  119. .grid-5 {
  120. display: grid; grid-template-columns: repeat(5, 1fr); gap: 10px;
  121. }
  122. .grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
  123. .span-2 { grid-column: span 2; }
  124. .field label {
  125. display: block; font-size: 11px; color: var(--text-muted); margin-bottom: 4px; font-weight: 500;
  126. }
  127. .field input, .field select, .field .ctrl {
  128. width: 100%; height: 36px; border: 1px solid var(--border); border-radius: 8px;
  129. padding: 0 10px; font: inherit; background: #fff;
  130. }
  131. .field .ctrl.muted { background: #f8fafc; color: var(--text-muted); }
  132. .btn {
  133. display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px;
  134. border-radius: 8px; border: 1px solid var(--border); background: #fff;
  135. font: inherit; font-weight: 600; font-size: 12px; cursor: pointer;
  136. }
  137. .btn.primary { background: var(--primary); border-color: var(--primary); color: #fff; }
  138. .btn.ghost { background: #fff; }
  139. .btn.sm { height: 28px; padding: 0 10px; font-size: 11px; }
  140. /* 产品信息简表 */
  141. .mini-table-wrap {
  142. border: 1px solid var(--border); border-radius: 8px; overflow: hidden; background: #fff;
  143. }
  144. table.mini {
  145. width: 100%; border-collapse: collapse; font-size: 12px; table-layout: fixed;
  146. }
  147. table.mini th, table.mini td {
  148. border-bottom: 1px solid var(--border); padding: 7px 8px; text-align: left;
  149. }
  150. table.mini th { background: var(--table-head); color: var(--text-muted); font-size: 11px; font-weight: 600; }
  151. table.mini tr:last-child td { border-bottom: none; }
  152. .tag {
  153. display: inline-flex; padding: 1px 6px; border-radius: 4px;
  154. font-size: 10px; font-weight: 600;
  155. }
  156. .tag.danger { background: var(--danger); color: #fff; }
  157. /* ===== 装货左 / 送货右 主分栏 ===== */
  158. .stops-split {
  159. display: grid;
  160. grid-template-columns: 1fr 1fr;
  161. gap: 0;
  162. border: 1px solid var(--border);
  163. border-radius: var(--radius);
  164. overflow: hidden;
  165. background: #fff;
  166. min-height: 420px;
  167. }
  168. .stops-split.ratio-46 { grid-template-columns: 0.46fr 0.54fr; }
  169. .stop-pane {
  170. display: flex; flex-direction: column; min-width: 0; min-height: 0;
  171. }
  172. .stop-pane + .stop-pane { border-left: 1px solid var(--border); }
  173. .stop-pane__hd {
  174. display: flex; align-items: center; justify-content: space-between; gap: 10px;
  175. padding: 10px 12px; border-bottom: 1px solid var(--border); flex-shrink: 0;
  176. }
  177. .stop-pane--load .stop-pane__hd { background: linear-gradient(180deg, #ecfdf5 0%, #f8fffc 100%); }
  178. .stop-pane--delivery .stop-pane__hd { background: linear-gradient(180deg, #f0f9ff 0%, #f8fcff 100%); }
  179. .stop-pane__title {
  180. margin: 0; font-size: 13px; font-weight: 700;
  181. display: flex; align-items: center; gap: 8px;
  182. }
  183. .stop-pane__title .dot {
  184. width: 8px; height: 8px; border-radius: 50%;
  185. }
  186. .stop-pane--load .stop-pane__title .dot { background: var(--primary); }
  187. .stop-pane--delivery .stop-pane__title .dot { background: var(--delivery-accent); }
  188. .stop-pane__bd {
  189. padding: 12px; flex: 1; overflow: auto; display: flex; flex-direction: column; gap: 10px;
  190. }
  191. .party-row { display: grid; grid-template-columns: 1fr; gap: 8px; }
  192. .party-row.two { grid-template-columns: 1.2fr 0.8fr; }
  193. .dibang-row {
  194. display: flex; align-items: center; gap: 8px; font-size: 12px; padding: 6px 0;
  195. }
  196. .dibang-row input { accent-color: var(--primary); width: 15px; height: 15px; }
  197. .products-head {
  198. display: flex; align-items: center; justify-content: space-between; gap: 8px;
  199. margin-top: 4px;
  200. }
  201. .products-head__label { font-size: 12px; font-weight: 600; color: var(--text-muted); }
  202. /* 段内紧凑产品表 */
  203. table.seg {
  204. width: 100%; border-collapse: collapse; font-size: 12px; table-layout: fixed;
  205. }
  206. table.seg th, table.seg td {
  207. border-bottom: 1px solid var(--border); padding: 6px 6px; vertical-align: middle;
  208. }
  209. table.seg th {
  210. background: var(--table-head); color: var(--text-muted);
  211. font-size: 10px; font-weight: 600; white-space: nowrap;
  212. }
  213. table.seg tr:last-child td { border-bottom: none; }
  214. table.seg input, table.seg select {
  215. width: 100%; height: 28px; border: 1px solid var(--border);
  216. border-radius: 6px; padding: 0 5px; font: inherit; font-size: 11px;
  217. }
  218. .subline { display: block; font-size: 10px; color: var(--text-muted); margin-top: 2px; line-height: 1.35; }
  219. .num { text-align: right; }
  220. .center { text-align: center; }
  221. /* 数量平衡条 */
  222. .balance-bar {
  223. display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px;
  224. padding: 8px 12px; border-top: 1px solid var(--border);
  225. background: #f8fafc; font-size: 11px; flex-shrink: 0;
  226. }
  227. .balance-bar .ok { color: var(--primary-dark); font-weight: 600; }
  228. .balance-bar .warn { color: var(--warn); font-weight: 600; }
  229. .balance-item { display: flex; align-items: center; gap: 4px; }
  230. .balance-item strong { font-weight: 700; }
  231. /* 送货段 Tab(方案 1) */
  232. .delivery-tabs {
  233. display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 4px;
  234. }
  235. .delivery-tab {
  236. border: 1px solid var(--border); background: #fff; border-radius: 6px;
  237. padding: 5px 10px; font-size: 11px; font-weight: 600; cursor: pointer;
  238. color: var(--text-muted); font-family: inherit;
  239. }
  240. .delivery-tab.active {
  241. border-color: #7dd3fc; background: var(--delivery-bg); color: var(--delivery-accent);
  242. }
  243. .delivery-tab .qty { font-weight: 400; color: var(--text-muted); margin-left: 4px; }
  244. .delivery-panel { display: none; flex-direction: column; gap: 10px; flex: 1; }
  245. .delivery-panel.active { display: flex; }
  246. .delivery-actions {
  247. display: flex; flex-wrap: wrap; gap: 4px; justify-content: flex-end;
  248. }
  249. /* 送货段堆叠卡片(方案 2) */
  250. .delivery-stack { display: flex; flex-direction: column; gap: 10px; }
  251. .delivery-card {
  252. border: 1px solid #bae6fd; border-radius: 8px; overflow: hidden; background: #fff;
  253. }
  254. .delivery-card__hd {
  255. display: flex; align-items: center; justify-content: space-between; gap: 8px;
  256. padding: 7px 10px; background: var(--delivery-bg); border-bottom: 1px solid #bae6fd;
  257. font-size: 12px; font-weight: 700; color: #0369a1;
  258. }
  259. .delivery-card__bd { padding: 10px; }
  260. /* 产品条(备选) */
  261. .product-strip {
  262. border: 1px solid var(--border); border-radius: 8px; padding: 7px 8px; background: #fff;
  263. font-size: 11px; margin-bottom: 6px;
  264. }
  265. .product-strip:last-child { margin-bottom: 0; }
  266. .product-strip__r1 { display: flex; gap: 6px; align-items: center; margin-bottom: 4px; }
  267. .product-strip__r1 .name { flex: 1; font-weight: 600; font-size: 12px; min-width: 0; }
  268. .product-strip__r1 .qty { width: 72px; flex-shrink: 0; }
  269. .product-strip__r1 .qty input { width: 100%; height: 26px; border: 1px solid var(--border); border-radius: 5px; padding: 0 4px; font: inherit; font-size: 11px; }
  270. .product-strip__meta { color: var(--text-muted); font-size: 10px; margin-bottom: 5px; }
  271. .product-strip__r2 { display: grid; grid-template-columns: 1fr 1fr; gap: 5px; }
  272. .product-strip__r2 label { display: block; font-size: 9px; color: var(--text-muted); margin-bottom: 1px; }
  273. .product-strip__r2 select, .product-strip__r2 input {
  274. width: 100%; height: 26px; border: 1px solid var(--border); border-radius: 5px;
  275. padding: 0 4px; font: inherit; font-size: 11px;
  276. }
  277. .pros-cons {
  278. display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 14px;
  279. }
  280. .pros-cons > div {
  281. border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; font-size: 12px;
  282. }
  283. .pros-cons h4 { margin: 0 0 6px; font-size: 12px; }
  284. .pros-cons ul { margin: 0; padding-left: 18px; color: var(--text-muted); }
  285. .flow-arrow {
  286. text-align: center; font-size: 11px; color: var(--text-muted);
  287. padding: 4px 0; border-top: 1px dashed var(--border); margin-top: auto;
  288. }
  289. @media (max-width: 1100px) {
  290. .stops-split, .stops-split.ratio-46 { grid-template-columns: 1fr; }
  291. .stop-pane + .stop-pane { border-left: none; border-top: 1px solid var(--border); }
  292. .grid-5 { grid-template-columns: repeat(2, 1fr); }
  293. }
  294. @media (max-width: 640px) {
  295. .grid-2, .party-row.two { grid-template-columns: 1fr; }
  296. .span-2 { grid-column: span 1; }
  297. }
  298. </style>
  299. </head>
  300. <body>
  301. <div class="page">
  302. <header class="hero">
  303. <h1>运输计划 · <em>装货左 / 送货右</em> 分栏 Demo</h1>
  304. <p>
  305. 在保留「基础信息 + 产品信息」全宽的前提下,将<strong>装货与送货并列左右</strong>,
  306. 形成「起点 → 终点」的视觉对照;每侧内部纵向排布(客户/地址在上,段内紧凑产品在下),
  307. 避免在 50% 栏宽里再嵌套「表单|产品」横分。
  308. </p>
  309. <div class="pills">
  310. <span class="pill">左:装货(1 段固定)</span>
  311. <span class="pill blue">右:送货(可多段)</span>
  312. <span class="pill muted">段内产品:6 列紧凑表 / 产品条,无横向滚动</span>
  313. </div>
  314. </header>
  315. <div class="toolbar">
  316. <label for="viewport">模拟弹窗宽度</label>
  317. <select id="viewport">
  318. <option value="1440">1440px</option>
  319. <option value="1280" selected>1280px</option>
  320. <option value="1100">1100px(分栏断点)</option>
  321. </select>
  322. </div>
  323. <div class="scheme-tabs">
  324. <button class="scheme-tab recommended active" data-scheme="tabs" type="button">方案 1 · 右栏送货 Tab</button>
  325. <button class="scheme-tab" data-scheme="stack" type="button">方案 2 · 右栏送货堆叠</button>
  326. <button class="scheme-tab" data-scheme="strips" type="button">方案 3 · 两侧产品条</button>
  327. </div>
  328. <!-- 方案 1 -->
  329. <section class="scheme-panel active" id="panel-tabs">
  330. <p class="scheme-desc ok">
  331. <strong>推荐:</strong>装货固定占左栏;右栏多个送货段用 <strong>Tab 切换</strong>,每次只展开一段的表单+产品,
  332. 避免 3 段送货纵向堆叠把弹窗撑得很高。底部横条展示数量平衡(装货合计 = 送货合计 = 计划总量)。
  333. </p>
  334. <div class="dialog-sim">
  335. <div class="dialog-sim__hd">编辑运输计划</div>
  336. <div class="dialog-sim__bd">
  337. <!-- 基础信息 -->
  338. <div class="section">
  339. <h3 class="section-title"><span>基础信息</span></h3>
  340. <div class="grid-5">
  341. <div class="field"><label>创建日期</label><input value="2026-08-26" readonly /></div>
  342. <div class="field"><label>计划日期</label><input value="2026-08-26" /></div>
  343. <div class="field"><label>归属公司</label><select><option>安庆山峡</option></select></div>
  344. <div class="field"><label>单据类型</label><select><option>直销单</option></select></div>
  345. <div class="field"><label>跟进人</label><input value="张三" readonly /></div>
  346. </div>
  347. </div>
  348. <!-- 产品信息 -->
  349. <div class="section">
  350. <h3 class="section-title">
  351. <span>产品信息(计划总量)</span>
  352. <button class="btn primary sm" type="button">+ 添加产品</button>
  353. </h3>
  354. <div class="mini-table-wrap">
  355. <table class="mini">
  356. <thead>
  357. <tr>
  358. <th style="width:4%">#</th>
  359. <th style="width:18%">产品名称</th>
  360. <th style="width:12%">别名</th>
  361. <th style="width:12%">品牌</th>
  362. <th style="width:10%">规格</th>
  363. <th style="width:6%">单位</th>
  364. <th style="width:10%">计划数量</th>
  365. <th style="width:10%">包装规格</th>
  366. <th style="width:10%">送货方式</th>
  367. <th>备注</th>
  368. </tr>
  369. </thead>
  370. <tbody>
  371. <tr>
  372. <td class="center">1</td>
  373. <td>97% 精制硫酸 <span class="tag danger">易制毒</span></td>
  374. <td class="center">工业硫酸</td>
  375. <td class="center">不限</td>
  376. <td>CP级</td>
  377. <td class="center">吨</td>
  378. <td class="num">30.000</td>
  379. <td class="center">槽罐</td>
  380. <td class="center">一票制</td>
  381. <td>—</td>
  382. </tr>
  383. </tbody>
  384. </table>
  385. </div>
  386. </div>
  387. <!-- 装货左 | 送货右 -->
  388. <div class="section">
  389. <h3 class="section-title"><span>装卸货信息</span></h3>
  390. <div class="stops-split">
  391. <!-- 左:装货 -->
  392. <div class="stop-pane stop-pane--load">
  393. <div class="stop-pane__hd">
  394. <h4 class="stop-pane__title"><span class="dot"></span>装货信息</h4>
  395. <button class="btn ghost sm" type="button">同步产品</button>
  396. </div>
  397. <div class="stop-pane__bd">
  398. <div class="party-row two">
  399. <div class="field"><label>装货客户 *</label><select><option>XX 硫酸供应商</option></select></div>
  400. <div class="field"><label>装货合同 *</label><button class="btn ghost sm" type="button" style="width:100%">选合同</button></div>
  401. </div>
  402. <div class="grid-2">
  403. <div class="field"><label>装货时间</label><input value="2026-08-26" /></div>
  404. <div class="field"><label>联系方式</label><input value="张工 138****0001" /></div>
  405. <div class="field span-2"><label>装货地址</label><input value="安庆市迎江区 · 供应商仓库" /></div>
  406. <div class="field span-2"><label>注意事项</label><input value="装货前联系仓库" /></div>
  407. </div>
  408. <div class="dibang-row"><input type="checkbox" checked /> 生成地磅单(出库)</div>
  409. <div class="products-head">
  410. <span class="products-head__label">装货产品</span>
  411. </div>
  412. <div class="mini-table-wrap">
  413. <table class="seg">
  414. <thead>
  415. <tr>
  416. <th style="width:8%">#</th>
  417. <th>产品</th>
  418. <th style="width:22%">计划数量</th>
  419. <th style="width:22%">包装</th>
  420. <th style="width:22%">送货方式</th>
  421. </tr>
  422. </thead>
  423. <tbody>
  424. <tr>
  425. <td class="center">1</td>
  426. <td>
  427. 97% 精制硫酸 <span class="tag danger">毒</span>
  428. <span class="subline">工业硫酸 · 不限 · CP级 · 吨</span>
  429. </td>
  430. <td class="num"><input value="30" /></td>
  431. <td><select><option>槽罐</option></select></td>
  432. <td><select><option>一票制</option></select></td>
  433. </tr>
  434. </tbody>
  435. </table>
  436. </div>
  437. <div class="flow-arrow">↓ 出库 · 一车多卸</div>
  438. </div>
  439. </div>
  440. <!-- 右:送货 -->
  441. <div class="stop-pane stop-pane--delivery">
  442. <div class="stop-pane__hd">
  443. <h4 class="stop-pane__title"><span class="dot"></span>送货信息</h4>
  444. <button class="btn primary sm" type="button">+ 添加送货段</button>
  445. </div>
  446. <div class="stop-pane__bd">
  447. <div class="delivery-tabs" id="deliveryTabs">
  448. <button class="delivery-tab active" data-panel="d1" type="button">
  449. #1 客户甲<span class="qty">10t</span>
  450. </button>
  451. <button class="delivery-tab" data-panel="d2" type="button">
  452. #2 客户乙<span class="qty">15t</span>
  453. </button>
  454. <button class="delivery-tab" data-panel="d3" type="button">
  455. #3 山峡<span class="qty">5t</span>
  456. </button>
  457. </div>
  458. <div class="delivery-panel active" id="panel-d1">
  459. <div class="delivery-actions">
  460. <button class="btn ghost sm" type="button">下移</button>
  461. <button class="btn ghost sm" type="button">删除</button>
  462. </div>
  463. <div class="party-row two">
  464. <div class="field"><label>送货客户 *</label><select><option>客户甲有限公司</option></select></div>
  465. <div class="field"><label>送货合同 *</label><button class="btn ghost sm" type="button" style="width:100%">选合同</button></div>
  466. </div>
  467. <div class="grid-2">
  468. <div class="field"><label>送货时间</label><input value="2026-08-27" /></div>
  469. <div class="field"><label>联系方式</label><input value="李经理" /></div>
  470. <div class="field span-2"><label>送货地址</label><input value="合肥市高新区 …" /></div>
  471. </div>
  472. <div class="dibang-row"><input type="checkbox" /> 生成地磅单(入库)</div>
  473. <div class="products-head"><span class="products-head__label">送货产品</span><button class="btn ghost sm" type="button">同步</button></div>
  474. <div class="mini-table-wrap">
  475. <table class="seg">
  476. <thead><tr><th style="width:8%">#</th><th>产品</th><th style="width:22%">计划数量</th><th style="width:22%">包装</th><th style="width:22%">送货方式</th></tr></thead>
  477. <tbody>
  478. <tr>
  479. <td class="center">1</td>
  480. <td>97% 精制硫酸<span class="subline">工业硫酸 · CP级 · 吨</span></td>
  481. <td class="num"><input value="10" /></td>
  482. <td><select><option>槽罐</option></select></td>
  483. <td><select><option>一票制</option></select></td>
  484. </tr>
  485. </tbody>
  486. </table>
  487. </div>
  488. </div>
  489. <div class="delivery-panel" id="panel-d2">
  490. <div class="delivery-actions">
  491. <button class="btn ghost sm" type="button">上移</button>
  492. <button class="btn ghost sm" type="button">下移</button>
  493. <button class="btn ghost sm" type="button">删除</button>
  494. </div>
  495. <div class="party-row two">
  496. <div class="field"><label>送货客户 *</label><select><option>客户乙科技</option></select></div>
  497. <div class="field"><label>送货合同 *</label><button class="btn ghost sm" type="button" style="width:100%">选合同</button></div>
  498. </div>
  499. <div class="grid-2">
  500. <div class="field"><label>送货时间</label><input value="2026-08-27" /></div>
  501. <div class="field"><label>送货地址</label><input value="芜湖市 …" /></div>
  502. </div>
  503. <div class="products-head"><span class="products-head__label">送货产品</span></div>
  504. <div class="mini-table-wrap">
  505. <table class="seg">
  506. <thead><tr><th style="width:8%">#</th><th>产品</th><th style="width:22%">计划数量</th><th style="width:22%">包装</th><th style="width:22%">送货方式</th></tr></thead>
  507. <tbody>
  508. <tr>
  509. <td class="center">1</td>
  510. <td>97% 精制硫酸</td>
  511. <td class="num"><input value="15" /></td>
  512. <td><select><option>槽罐</option></select></td>
  513. <td><select><option>客户自提</option></select></td>
  514. </tr>
  515. </tbody>
  516. </table>
  517. </div>
  518. </div>
  519. <div class="delivery-panel" id="panel-d3">
  520. <div class="party-row two">
  521. <div class="field"><label>送货客户 *</label><select><option>安庆市山峡化工有限公司</option></select></div>
  522. <div class="field"><label>送货合同</label><div class="ctrl muted" style="display:flex;align-items:center">内部 · 免合同</div></div>
  523. </div>
  524. <div class="dibang-row"><input type="checkbox" checked /> 生成地磅单(入库)</div>
  525. <div class="products-head"><span class="products-head__label">送货产品</span></div>
  526. <div class="mini-table-wrap">
  527. <table class="seg">
  528. <thead><tr><th style="width:8%">#</th><th>产品</th><th style="width:22%">计划数量</th><th style="width:22%">包装</th><th style="width:22%">送货方式</th></tr></thead>
  529. <tbody>
  530. <tr>
  531. <td class="center">1</td>
  532. <td>97% 精制硫酸</td>
  533. <td class="num"><input value="5" /></td>
  534. <td><select><option>槽罐</option></select></td>
  535. <td><select><option>山峡自提</option></select></td>
  536. </tr>
  537. </tbody>
  538. </table>
  539. </div>
  540. </div>
  541. </div>
  542. </div>
  543. <!-- 数量平衡 -->
  544. <div class="balance-bar" style="grid-column: 1 / -1; border-top: 1px solid var(--border);">
  545. <span class="balance-item">计划总量 <strong>30t</strong></span>
  546. <span class="balance-item">装货合计 <strong>30t</strong></span>
  547. <span class="balance-item">送货合计 <strong>30t</strong></span>
  548. <span class="ok">✓ 数量平衡</span>
  549. <span style="margin-left:auto;color:var(--text-muted)">10 + 15 + 5 = 30</span>
  550. </div>
  551. </div>
  552. </div>
  553. <!-- 运输信息占位 -->
  554. <div class="section" style="margin-bottom:0">
  555. <h3 class="section-title"><span>运输信息</span></h3>
  556. <div class="grid-2">
  557. <div class="field"><label>车牌号</label><select><option>皖H12345</option></select></div>
  558. <div class="field"><label>承运商</label><select><option>某某物流</option></select></div>
  559. </div>
  560. </div>
  561. </div>
  562. </div>
  563. <div class="pros-cons">
  564. <div>
  565. <h4>优点</h4>
  566. <ul>
  567. <li>装货↔送货左右对照,符合「起点→终点」心智</li>
  568. <li>充分利用弹窗宽度,比上下堆叠<strong>省纵向高度</strong></li>
  569. <li>右栏 Tab 切换多段送货,避免 3 段卡片纵向过长</li>
  570. <li>段内 5 列紧凑表,50% 栏宽无横向滚动</li>
  571. </ul>
  572. </div>
  573. <div>
  574. <h4>注意点</h4>
  575. <ul>
  576. <li>每侧仅 ~640px,段内不宜再用 10 列宽表</li>
  577. <li>送货 Tab 需显示客户名 + 数量摘要,方便切换</li>
  578. <li>&lt;1100px 时左右改为上下(装货上、送货下)</li>
  579. </ul>
  580. </div>
  581. </div>
  582. </section>
  583. <!-- 方案 2:堆叠 -->
  584. <section class="scheme-panel" id="panel-stack">
  585. <p class="scheme-desc">
  586. 同样装货左 / 送货右,但右栏<strong>多个送货段纵向堆叠</strong>(接近现状)。
  587. 适合送货段 ≤2 个;3 段以上右栏会很高,需内部滚动。
  588. </p>
  589. <div class="dialog-sim">
  590. <div class="dialog-sim__hd">编辑运输计划 · 方案 2</div>
  591. <div class="dialog-sim__bd">
  592. <div class="stops-split ratio-46" style="min-height:480px">
  593. <div class="stop-pane stop-pane--load">
  594. <div class="stop-pane__hd">
  595. <h4 class="stop-pane__title"><span class="dot"></span>装货信息</h4>
  596. </div>
  597. <div class="stop-pane__bd">
  598. <div class="field"><label>装货客户</label><select><option>XX 硫酸供应商</option></select></div>
  599. <div class="field"><label>装货地址</label><input value="安庆市迎江区 …" /></div>
  600. <div class="field"><label>装货时间</label><input value="2026-08-26" /></div>
  601. <div class="products-head"><span class="products-head__label">装货产品</span></div>
  602. <div class="mini-table-wrap">
  603. <table class="seg">
  604. <thead><tr><th style="width:8%">#</th><th>产品</th><th style="width:24%">数量</th><th style="width:24%">包装</th></tr></thead>
  605. <tbody><tr><td class="center">1</td><td>97% 精制硫酸</td><td class="num"><input value="30" /></td><td><select><option>槽罐</option></select></td></tr></tbody>
  606. </table>
  607. </div>
  608. </div>
  609. </div>
  610. <div class="stop-pane stop-pane--delivery">
  611. <div class="stop-pane__hd">
  612. <h4 class="stop-pane__title"><span class="dot"></span>送货信息</h4>
  613. <button class="btn primary sm" type="button">+ 添加</button>
  614. </div>
  615. <div class="stop-pane__bd" style="overflow-y:auto;max-height:440px">
  616. <div class="delivery-stack">
  617. <article class="delivery-card">
  618. <div class="delivery-card__hd">送货段 #1 · 客户甲 <span style="font-weight:400;color:var(--text-muted)">10t</span></div>
  619. <div class="delivery-card__bd">
  620. <div class="field"><label>送货客户</label><select><option>客户甲</option></select></div>
  621. <div class="field"><label>送货地址</label><input value="合肥市 …" /></div>
  622. <table class="seg" style="margin-top:6px"><thead><tr><th>#</th><th>产品</th><th style="width:28%">数量</th></tr></thead>
  623. <tbody><tr><td class="center">1</td><td>硫酸</td><td class="num"><input value="10" /></td></tr></tbody></table>
  624. </div>
  625. </article>
  626. <article class="delivery-card">
  627. <div class="delivery-card__hd">送货段 #2 · 客户乙 <span style="font-weight:400">15t</span></div>
  628. <div class="delivery-card__bd">
  629. <div class="field"><label>送货客户</label><select><option>客户乙</option></select></div>
  630. <table class="seg" style="margin-top:6px"><thead><tr><th>#</th><th>产品</th><th style="width:28%">数量</th></tr></thead>
  631. <tbody><tr><td class="center">1</td><td>硫酸</td><td class="num"><input value="15" /></td></tr></tbody></table>
  632. </div>
  633. </article>
  634. <article class="delivery-card">
  635. <div class="delivery-card__hd">送货段 #3 · 山峡 <span style="font-weight:400">5t</span></div>
  636. <div class="delivery-card__bd">
  637. <div class="field"><label>送货客户</label><select><option>山峡化工</option></select></div>
  638. <table class="seg" style="margin-top:6px"><thead><tr><th>#</th><th>产品</th><th style="width:28%">数量</th></tr></thead>
  639. <tbody><tr><td class="center">1</td><td>硫酸</td><td class="num"><input value="5" /></td></tr></tbody></table>
  640. </div>
  641. </article>
  642. </div>
  643. </div>
  644. </div>
  645. </div>
  646. </div>
  647. </div>
  648. <div class="pros-cons">
  649. <div><h4>优点</h4><ul><li>所有送货段同屏可见,无需切换 Tab</li><li>与现有送货卡片组件接近</li></ul></div>
  650. <div><h4>缺点</h4><ul><li>3 段以上右栏过高,通常要内部滚动</li><li>左右两栏高度难对齐</li></ul></div>
  651. </div>
  652. </section>
  653. <!-- 方案 3:产品条 -->
  654. <section class="scheme-panel" id="panel-strips">
  655. <p class="scheme-desc ok">
  656. 装货左 / 送货右 + 右栏 Tab;两侧产品区改用<strong>产品条</strong>(每条 2 行),
  657. 在 50% 栏宽下比表格更灵活,多产品时也无需横向滚动。
  658. </p>
  659. <div class="dialog-sim">
  660. <div class="dialog-sim__hd">编辑运输计划 · 方案 3</div>
  661. <div class="dialog-sim__bd">
  662. <div class="stops-split" style="min-height:380px">
  663. <div class="stop-pane stop-pane--load">
  664. <div class="stop-pane__hd"><h4 class="stop-pane__title"><span class="dot"></span>装货信息</h4></div>
  665. <div class="stop-pane__bd">
  666. <div class="party-row two">
  667. <div class="field"><label>装货客户</label><select><option>XX 供应商</option></select></div>
  668. <div class="field"><label>合同</label><button class="btn ghost sm" type="button" style="width:100%">选合同</button></div>
  669. </div>
  670. <div class="field"><label>装货地址</label><input value="安庆市 …" /></div>
  671. <div class="products-head"><span class="products-head__label">装货产品</span></div>
  672. <div class="product-strip">
  673. <div class="product-strip__r1">
  674. <div class="name">97% 精制硫酸 <span class="tag danger">毒</span></div>
  675. <div class="qty"><input value="30" title="计划数量" /></div>
  676. </div>
  677. <div class="product-strip__meta">工业硫酸 · 不限 · CP级 · 吨</div>
  678. <div class="product-strip__r2">
  679. <div><label>包装</label><select><option>槽罐</option></select></div>
  680. <div><label>送货方式</label><select><option>一票制</option></select></div>
  681. </div>
  682. </div>
  683. <div class="product-strip">
  684. <div class="product-strip__r1">
  685. <div class="name">30% 液碱</div>
  686. <div class="qty"><input value="0" /></div>
  687. </div>
  688. <div class="product-strip__meta">天原 · 国标 · 吨</div>
  689. <div class="product-strip__r2">
  690. <div><label>包装</label><select><option>散装</option></select></div>
  691. <div><label>送货方式</label><select><option>自提</option></select></div>
  692. </div>
  693. </div>
  694. </div>
  695. </div>
  696. <div class="stop-pane stop-pane--delivery">
  697. <div class="stop-pane__hd">
  698. <h4 class="stop-pane__title"><span class="dot"></span>送货信息</h4>
  699. <button class="btn primary sm" type="button">+ 添加</button>
  700. </div>
  701. <div class="stop-pane__bd">
  702. <div class="delivery-tabs">
  703. <button class="delivery-tab active" type="button">#1 客户甲 10t</button>
  704. <button class="delivery-tab" type="button">#2 客户乙 15t</button>
  705. </div>
  706. <div class="field"><label>送货客户</label><select><option>客户甲</option></select></div>
  707. <div class="field"><label>送货地址</label><input value="合肥市 …" /></div>
  708. <div class="products-head"><span class="products-head__label">送货产品</span></div>
  709. <div class="product-strip">
  710. <div class="product-strip__r1">
  711. <div class="name">97% 精制硫酸</div>
  712. <div class="qty"><input value="10" /></div>
  713. </div>
  714. <div class="product-strip__meta">工业硫酸 · CP级 · 吨</div>
  715. <div class="product-strip__r2">
  716. <div><label>包装</label><select><option>槽罐</option></select></div>
  717. <div><label>送货方式</label><select><option>一票制</option></select></div>
  718. </div>
  719. </div>
  720. </div>
  721. </div>
  722. </div>
  723. </div>
  724. </div>
  725. <div class="pros-cons">
  726. <div><h4>优点</h4><ul><li>最适配窄栏宽,多产品也清晰</li><li>装货/送货左右对照 + 省高度</li></ul></div>
  727. <div><h4>缺点</h4><ul><li>非表格形态,与上方产品信息表风格不同</li></ul></div>
  728. </div>
  729. </section>
  730. </div>
  731. <script>
  732. document.querySelectorAll('.scheme-tab').forEach((tab) => {
  733. tab.addEventListener('click', () => {
  734. const scheme = tab.dataset.scheme
  735. document.querySelectorAll('.scheme-tab').forEach((t) => t.classList.toggle('active', t === tab))
  736. document.querySelectorAll('.scheme-panel').forEach((p) => p.classList.toggle('active', p.id === `panel-${scheme}`))
  737. })
  738. })
  739. document.getElementById('viewport').addEventListener('change', (e) => {
  740. document.documentElement.style.setProperty('--dialog-max', `${e.target.value}px`)
  741. })
  742. document.getElementById('deliveryTabs')?.addEventListener('click', (e) => {
  743. const tab = e.target.closest('.delivery-tab')
  744. if (!tab) return
  745. const panelId = tab.dataset.panel
  746. document.querySelectorAll('#deliveryTabs .delivery-tab').forEach((t) => t.classList.toggle('active', t === tab))
  747. document.querySelectorAll('.delivery-panel').forEach((p) => p.classList.toggle('active', p.id === `panel-${panelId}`))
  748. })
  749. </script>
  750. </body>
  751. </html>