2026-07-19-pl-outbound-site-link-demo.html 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813
  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, maximum-scale=1, user-scalable=no" />
  6. <title>现场链接 · 出库单公共页 Demo</title>
  7. <style>
  8. :root {
  9. --primary: #059669;
  10. --primary-bright: #10b981;
  11. --primary-bg: #ecfdf5;
  12. --primary-soft: #e6f8ed;
  13. --text: #0f172a;
  14. --text-secondary: #1e293b;
  15. --muted: #64748b;
  16. --muted-light: #94a3b8;
  17. --border: #e2e8f0;
  18. --page-bg: #f1f5f9;
  19. --card: #fff;
  20. --danger: #ef4444;
  21. --warning-bg: #fffbeb;
  22. --warning-text: #b45309;
  23. }
  24. * { box-sizing: border-box; margin: 0; padding: 0; }
  25. body {
  26. font-family: -apple-system, BlinkMacSystemFont, "PingFang SC", "Helvetica Neue", sans-serif;
  27. background: #0f172a;
  28. color: var(--text);
  29. min-height: 100vh;
  30. padding: 24px 16px 48px;
  31. }
  32. .demo-header {
  33. max-width: 960px;
  34. margin: 0 auto 20px;
  35. color: #e2e8f0;
  36. }
  37. .demo-header h1 {
  38. font-size: 20px;
  39. font-weight: 700;
  40. margin-bottom: 6px;
  41. }
  42. .demo-header p {
  43. font-size: 13px;
  44. color: #94a3b8;
  45. line-height: 1.5;
  46. }
  47. .demo-header .tags {
  48. display: flex;
  49. flex-wrap: wrap;
  50. gap: 8px;
  51. margin-top: 12px;
  52. }
  53. .demo-header .tag {
  54. font-size: 11px;
  55. padding: 4px 10px;
  56. border-radius: 999px;
  57. background: #1e293b;
  58. color: #a7f3d0;
  59. border: 1px solid #334155;
  60. }
  61. .tabs {
  62. max-width: 960px;
  63. margin: 0 auto 16px;
  64. display: flex;
  65. gap: 8px;
  66. }
  67. .tabs button {
  68. flex: 1;
  69. border: 1px solid #334155;
  70. background: #1e293b;
  71. color: #94a3b8;
  72. padding: 10px 12px;
  73. border-radius: 10px;
  74. font-size: 13px;
  75. font-weight: 600;
  76. cursor: pointer;
  77. }
  78. .tabs button.active {
  79. background: var(--primary);
  80. border-color: var(--primary);
  81. color: #fff;
  82. }
  83. .phones {
  84. max-width: 960px;
  85. margin: 0 auto;
  86. display: flex;
  87. flex-wrap: wrap;
  88. gap: 24px;
  89. justify-content: center;
  90. }
  91. .phone-wrap {
  92. display: none;
  93. flex-direction: column;
  94. align-items: center;
  95. gap: 10px;
  96. }
  97. .phone-wrap.show { display: flex; }
  98. .phone-wrap.dual { display: none; }
  99. .phones.show-dual .phone-wrap.dual { display: flex; }
  100. .phones.show-dual .phone-wrap.single { display: none; }
  101. .phone-label {
  102. font-size: 12px;
  103. color: #94a3b8;
  104. font-weight: 600;
  105. }
  106. .phone {
  107. width: 375px;
  108. height: 720px;
  109. background: var(--page-bg);
  110. border-radius: 28px;
  111. border: 3px solid #334155;
  112. box-shadow: 0 20px 50px rgba(0,0,0,.45);
  113. overflow: hidden;
  114. display: flex;
  115. flex-direction: column;
  116. position: relative;
  117. }
  118. .nav {
  119. background: var(--primary);
  120. color: #fff;
  121. height: 46px;
  122. display: flex;
  123. align-items: center;
  124. justify-content: center;
  125. font-size: 16px;
  126. font-weight: 600;
  127. flex-shrink: 0;
  128. }
  129. .scroll {
  130. flex: 1;
  131. overflow-y: auto;
  132. padding: 12px 12px 88px;
  133. -webkit-overflow-scrolling: touch;
  134. }
  135. .card {
  136. background: var(--card);
  137. border-radius: 12px;
  138. margin-bottom: 10px;
  139. overflow: hidden;
  140. box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
  141. }
  142. .card-title {
  143. display: flex;
  144. align-items: center;
  145. gap: 6px;
  146. padding: 8px 12px 4px;
  147. font-size: 12px;
  148. font-weight: 600;
  149. color: #047857;
  150. background: linear-gradient(90deg, #ecfdf5 0%, rgba(236,253,245,0) 72%);
  151. }
  152. .card-title::before {
  153. content: "";
  154. width: 3px;
  155. height: 12px;
  156. border-radius: 2px;
  157. background: var(--primary);
  158. flex-shrink: 0;
  159. }
  160. .cell {
  161. display: flex;
  162. justify-content: space-between;
  163. align-items: flex-start;
  164. gap: 12px;
  165. padding: 9px 14px;
  166. border-bottom: 1px solid #f1f5f9;
  167. font-size: 14px;
  168. line-height: 1.35;
  169. }
  170. .cell:last-child { border-bottom: none; }
  171. .cell .label { color: var(--muted); flex-shrink: 0; min-width: 72px; }
  172. .cell .value {
  173. color: var(--text-secondary);
  174. font-weight: 600;
  175. text-align: right;
  176. word-break: break-all;
  177. }
  178. .cell.multiline .value { text-align: left; font-weight: 500; }
  179. .addr-row {
  180. display: flex;
  181. flex-wrap: wrap;
  182. align-items: center;
  183. gap: 6px 8px;
  184. justify-content: flex-end;
  185. }
  186. .addr-text { font-weight: 600; color: var(--text-secondary); text-align: right; }
  187. .nav-btn {
  188. flex-shrink: 0;
  189. height: 22px;
  190. padding: 0 8px;
  191. font-size: 11px;
  192. line-height: 22px;
  193. border-radius: 999px;
  194. border: none;
  195. background: var(--primary);
  196. color: #fff;
  197. font-weight: 600;
  198. cursor: pointer;
  199. }
  200. /* —— 现状:简陋产品数量 —— */
  201. .qty-old {
  202. padding: 10px 14px 4px;
  203. }
  204. .qty-old__name {
  205. font-weight: 600;
  206. color: var(--text);
  207. font-size: 14px;
  208. }
  209. .qty-old__spec {
  210. margin-left: 8px;
  211. font-weight: 400;
  212. color: var(--muted);
  213. font-size: 12px;
  214. }
  215. .qty-old__plan {
  216. margin-top: 4px;
  217. font-size: 12px;
  218. color: var(--muted-light);
  219. }
  220. .qty-old__field {
  221. display: flex;
  222. align-items: center;
  223. justify-content: space-between;
  224. padding: 10px 0 12px;
  225. border-bottom: 1px solid #f1f5f9;
  226. font-size: 14px;
  227. }
  228. .qty-old__field:last-child { border-bottom: none; }
  229. .qty-old__input {
  230. width: 120px;
  231. height: 32px;
  232. border: 1px solid var(--border);
  233. border-radius: 6px;
  234. padding: 0 10px;
  235. text-align: right;
  236. font-size: 14px;
  237. color: var(--text);
  238. background: #f8fafc;
  239. }
  240. /* —— 提案:美化产品实际数量 —— */
  241. .product-card {
  242. margin: 10px 12px;
  243. padding: 14px;
  244. border-radius: 12px;
  245. background: linear-gradient(180deg, #f0fdf4 0%, #fff 48%);
  246. border: 1px solid #d1fae5;
  247. }
  248. .product-card + .product-card { margin-top: 0; }
  249. .product-card__head {
  250. display: flex;
  251. align-items: flex-start;
  252. justify-content: space-between;
  253. gap: 8px;
  254. margin-bottom: 10px;
  255. }
  256. .product-card__name {
  257. font-size: 15px;
  258. font-weight: 700;
  259. color: var(--text);
  260. line-height: 1.35;
  261. }
  262. .product-card__badge {
  263. flex-shrink: 0;
  264. font-size: 10px;
  265. font-weight: 600;
  266. padding: 2px 8px;
  267. border-radius: 999px;
  268. background: #d1fae5;
  269. color: #047857;
  270. }
  271. .meta-grid {
  272. display: grid;
  273. grid-template-columns: 1fr 1fr;
  274. gap: 8px;
  275. margin-bottom: 12px;
  276. }
  277. .meta-item {
  278. background: rgba(255,255,255,.85);
  279. border: 1px solid #e2e8f0;
  280. border-radius: 8px;
  281. padding: 8px 10px;
  282. }
  283. .meta-item.span-2 { grid-column: 1 / -1; }
  284. .meta-item__label {
  285. font-size: 11px;
  286. color: var(--muted);
  287. margin-bottom: 2px;
  288. }
  289. .meta-item__value {
  290. font-size: 13px;
  291. font-weight: 600;
  292. color: var(--text-secondary);
  293. word-break: break-all;
  294. }
  295. .meta-item__value.plan {
  296. color: var(--primary);
  297. font-size: 15px;
  298. }
  299. .actual-box {
  300. background: #fff;
  301. border: 1px solid #a7f3d0;
  302. border-radius: 10px;
  303. padding: 10px 12px;
  304. }
  305. .actual-box__label {
  306. display: flex;
  307. align-items: center;
  308. justify-content: space-between;
  309. margin-bottom: 8px;
  310. font-size: 12px;
  311. color: var(--muted);
  312. }
  313. .actual-box__label strong {
  314. color: var(--text-secondary);
  315. font-size: 13px;
  316. }
  317. .actual-box__row {
  318. display: flex;
  319. align-items: center;
  320. gap: 8px;
  321. }
  322. .actual-box__input {
  323. flex: 1;
  324. height: 40px;
  325. border: 1.5px solid #6ee7b7;
  326. border-radius: 8px;
  327. padding: 0 12px;
  328. font-size: 18px;
  329. font-weight: 700;
  330. color: var(--primary);
  331. background: var(--primary-bg);
  332. outline: none;
  333. }
  334. .actual-box__input:focus {
  335. border-color: var(--primary);
  336. box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.15);
  337. }
  338. .actual-box__unit {
  339. flex-shrink: 0;
  340. font-size: 14px;
  341. font-weight: 700;
  342. color: var(--primary);
  343. min-width: 28px;
  344. }
  345. .actual-hint {
  346. margin-top: 6px;
  347. font-size: 11px;
  348. color: var(--muted-light);
  349. }
  350. .uploader {
  351. padding: 12px 14px;
  352. display: flex;
  353. gap: 10px;
  354. flex-wrap: wrap;
  355. }
  356. .upload-slot {
  357. width: 72px;
  358. height: 72px;
  359. border-radius: 8px;
  360. border: 1.5px dashed #a7f3d0;
  361. background: var(--primary-soft);
  362. display: flex;
  363. flex-direction: column;
  364. align-items: center;
  365. justify-content: center;
  366. color: #168f45;
  367. font-size: 11px;
  368. gap: 4px;
  369. }
  370. .upload-slot .plus { font-size: 22px; line-height: 1; font-weight: 300; }
  371. .upload-preview {
  372. width: 72px;
  373. height: 72px;
  374. border-radius: 8px;
  375. background: linear-gradient(135deg, #d1fae5, #a7f3d0);
  376. display: flex;
  377. align-items: center;
  378. justify-content: center;
  379. font-size: 11px;
  380. color: #047857;
  381. font-weight: 600;
  382. }
  383. .remark-area {
  384. padding: 8px 14px 14px;
  385. }
  386. .remark-area textarea {
  387. width: 100%;
  388. min-height: 88px;
  389. border: 1px solid var(--border);
  390. border-radius: 8px;
  391. padding: 10px 12px;
  392. font-size: 14px;
  393. line-height: 1.45;
  394. resize: none;
  395. color: var(--text);
  396. font-family: inherit;
  397. background: #f8fafc;
  398. }
  399. .footer {
  400. position: absolute;
  401. left: 0;
  402. right: 0;
  403. bottom: 0;
  404. padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0));
  405. background: rgba(255,255,255,.96);
  406. border-top: 1px solid var(--border);
  407. backdrop-filter: blur(8px);
  408. }
  409. .footer button {
  410. width: 100%;
  411. height: 44px;
  412. border: none;
  413. border-radius: 999px;
  414. background: var(--primary);
  415. color: #fff;
  416. font-size: 16px;
  417. font-weight: 600;
  418. cursor: pointer;
  419. }
  420. .diff-note {
  421. max-width: 960px;
  422. margin: 24px auto 0;
  423. background: #1e293b;
  424. border: 1px solid #334155;
  425. border-radius: 12px;
  426. padding: 16px 18px;
  427. color: #cbd5e1;
  428. font-size: 13px;
  429. line-height: 1.55;
  430. }
  431. .diff-note h2 {
  432. font-size: 14px;
  433. color: #a7f3d0;
  434. margin-bottom: 10px;
  435. }
  436. .diff-note ul { padding-left: 18px; }
  437. .diff-note li { margin-bottom: 6px; }
  438. .diff-note code {
  439. background: #0f172a;
  440. padding: 1px 6px;
  441. border-radius: 4px;
  442. font-size: 12px;
  443. color: #fde68a;
  444. }
  445. @media (max-width: 420px) {
  446. .phone { width: 100%; max-width: 375px; height: 680px; }
  447. }
  448. </style>
  449. </head>
  450. <body>
  451. <div class="demo-header">
  452. <h1>现场链接 · 出库单公共页 Demo</h1>
  453. <p>
  454. 对照「旧版运输现场」与「当前出库单现场链接」差异,提案页补回取送货信息,并美化「产品实际数量」
  455. (单位显示「吨」、展示包装规格)。可在浏览器直接打开本文件预览。
  456. </p>
  457. <div class="tags">
  458. <span class="tag">路由 /#/public/pl/outbound/:token</span>
  459. <span class="tag">对齐旧版 site 信息密度</span>
  460. <span class="tag">保留新版:填实际数量 + 回执</span>
  461. </div>
  462. </div>
  463. <div class="tabs">
  464. <button type="button" class="active" data-tab="proposed">提案(完善后)</button>
  465. <button type="button" data-tab="current">现状(数据少)</button>
  466. <button type="button" data-tab="compare">左右对照</button>
  467. </div>
  468. <div class="phones" id="phones">
  469. <!-- 提案:完善后 -->
  470. <div class="phone-wrap single show" data-panel="proposed">
  471. <div class="phone-label">提案 · 完善后的现场链接</div>
  472. <div class="phone">
  473. <div class="nav">出库单 · 现场回执</div>
  474. <div class="scroll">
  475. <div class="card">
  476. <div class="cell"><span class="label">业务类型</span><span class="value">出库</span></div>
  477. <div class="cell"><span class="label">日期</span><span class="value">2026-07-19</span></div>
  478. <div class="cell"><span class="label">往来单位</span><span class="value">安徽某某化工有限公司</span></div>
  479. <div class="cell"><span class="label">车牌</span><span class="value">皖H·A1234</span></div>
  480. <div class="cell"><span class="label">计划号</span><span class="value">YS20260719001</span></div>
  481. <div class="cell"><span class="label">单号</span><span class="value">CK20260719003</span></div>
  482. <div class="cell"><span class="label">状态</span><span class="value">进行中</span></div>
  483. <div class="cell multiline"><span class="label">备注</span><span class="value">请按计划数量装车,现场核对包装规格。</span></div>
  484. </div>
  485. <div class="card">
  486. <div class="card-title">取货信息</div>
  487. <div class="cell multiline">
  488. <span class="label">取货地址</span>
  489. <span class="value">
  490. <span class="addr-row">
  491. <span class="addr-text">安庆市迎江区某某路 88 号仓库</span>
  492. <button type="button" class="nav-btn">导航</button>
  493. </span>
  494. </span>
  495. </div>
  496. <div class="cell"><span class="label">取货时间</span><span class="value">2026-07-19 09:30</span></div>
  497. <div class="cell multiline"><span class="label">注意事项</span><span class="value">需佩戴安全帽,进厂登记。</span></div>
  498. </div>
  499. <div class="card">
  500. <div class="card-title">送货信息</div>
  501. <div class="cell multiline">
  502. <span class="label">送货地址</span>
  503. <span class="value">
  504. <span class="addr-row">
  505. <span class="addr-text">合肥市包河区某某工业园 3 栋</span>
  506. <button type="button" class="nav-btn">导航</button>
  507. </span>
  508. </span>
  509. </div>
  510. <div class="cell"><span class="label">送达时间</span><span class="value">2026-07-19 15:00</span></div>
  511. <div class="cell multiline"><span class="label">注意事项</span><span class="value">卸货区靠北门,联系仓库张工。</span></div>
  512. </div>
  513. <div class="card">
  514. <div class="card-title">产品实际数量</div>
  515. <div class="product-card">
  516. <div class="product-card__head">
  517. <div class="product-card__name">工业级尿素</div>
  518. <span class="product-card__badge">产品 1/2</span>
  519. </div>
  520. <div class="meta-grid">
  521. <div class="meta-item">
  522. <div class="meta-item__label">规格型号</div>
  523. <div class="meta-item__value">46.4%</div>
  524. </div>
  525. <div class="meta-item">
  526. <div class="meta-item__label">包装规格</div>
  527. <div class="meta-item__value">50kg/袋</div>
  528. </div>
  529. <div class="meta-item span-2">
  530. <div class="meta-item__label">计划数量</div>
  531. <div class="meta-item__value plan">32.000 吨</div>
  532. </div>
  533. </div>
  534. <div class="actual-box">
  535. <div class="actual-box__label">
  536. <strong>实际数量</strong>
  537. <span>请按现场实装填写</span>
  538. </div>
  539. <div class="actual-box__row">
  540. <input class="actual-box__input" type="number" value="32" step="0.001" />
  541. <span class="actual-box__unit">吨</span>
  542. </div>
  543. <div class="actual-hint">单位已按字典转中文(dun → 吨),勿直接展示字典码</div>
  544. </div>
  545. </div>
  546. <div class="product-card">
  547. <div class="product-card__head">
  548. <div class="product-card__name">片碱</div>
  549. <span class="product-card__badge">产品 2/2</span>
  550. </div>
  551. <div class="meta-grid">
  552. <div class="meta-item">
  553. <div class="meta-item__label">规格型号</div>
  554. <div class="meta-item__value">99%</div>
  555. </div>
  556. <div class="meta-item">
  557. <div class="meta-item__label">包装规格</div>
  558. <div class="meta-item__value">25kg/袋</div>
  559. </div>
  560. <div class="meta-item span-2">
  561. <div class="meta-item__label">计划数量</div>
  562. <div class="meta-item__value plan">8.500 吨</div>
  563. </div>
  564. </div>
  565. <div class="actual-box">
  566. <div class="actual-box__label">
  567. <strong>实际数量</strong>
  568. <span>请按现场实装填写</span>
  569. </div>
  570. <div class="actual-box__row">
  571. <input class="actual-box__input" type="number" value="8.5" step="0.001" />
  572. <span class="actual-box__unit">吨</span>
  573. </div>
  574. </div>
  575. </div>
  576. </div>
  577. <div class="card">
  578. <div class="card-title">回执上传</div>
  579. <div class="uploader">
  580. <div class="upload-preview">磅单.jpg</div>
  581. <div class="upload-slot"><span class="plus">+</span>上传</div>
  582. </div>
  583. </div>
  584. <div class="card">
  585. <div class="card-title">现场备注</div>
  586. <div class="remark-area">
  587. <textarea placeholder="填写现场备注">装车正常,包装完好。</textarea>
  588. </div>
  589. </div>
  590. <div class="card">
  591. <div class="cell"><span class="label">上次保存</span><span class="value">2026-07-19 10:21</span></div>
  592. </div>
  593. </div>
  594. <div class="footer">
  595. <button type="button">提交</button>
  596. </div>
  597. </div>
  598. </div>
  599. <!-- 现状 -->
  600. <div class="phone-wrap single" data-panel="current">
  601. <div class="phone-label">现状 · 数据偏少</div>
  602. <div class="phone">
  603. <div class="nav">出库单</div>
  604. <div class="scroll">
  605. <div class="card">
  606. <div class="cell"><span class="label">单号</span><span class="value">CK20260719003</span></div>
  607. <div class="cell"><span class="label">状态</span><span class="value">进行中</span></div>
  608. <div class="cell"><span class="label">往来单位</span><span class="value">安徽某某化工有限公司</span></div>
  609. <div class="cell"><span class="label">车牌</span><span class="value">皖H·A1234</span></div>
  610. <div class="cell"><span class="label">计划号</span><span class="value">YS20260719001</span></div>
  611. </div>
  612. <div class="card">
  613. <div class="card-title">产品实际数量</div>
  614. <div class="qty-old">
  615. <div class="qty-old__name">
  616. 工业级尿素
  617. <span class="qty-old__spec">46.4%</span>
  618. </div>
  619. <div class="qty-old__plan">计划 32 dun</div>
  620. <div class="qty-old__field">
  621. <span class="label">实际数量</span>
  622. <input class="qty-old__input" type="number" value="32" />
  623. </div>
  624. </div>
  625. <div class="qty-old">
  626. <div class="qty-old__name">
  627. 片碱
  628. <span class="qty-old__spec">99%</span>
  629. </div>
  630. <div class="qty-old__plan">计划 8.5 dun</div>
  631. <div class="qty-old__field">
  632. <span class="label">实际数量</span>
  633. <input class="qty-old__input" type="number" value="8.5" />
  634. </div>
  635. </div>
  636. </div>
  637. <div class="card">
  638. <div class="card-title">回执上传</div>
  639. <div class="uploader">
  640. <div class="upload-slot"><span class="plus">+</span>上传</div>
  641. </div>
  642. </div>
  643. <div class="card">
  644. <div class="card-title">现场备注</div>
  645. <div class="remark-area">
  646. <textarea placeholder="填写现场备注"></textarea>
  647. </div>
  648. </div>
  649. </div>
  650. <div class="footer">
  651. <button type="button">提交</button>
  652. </div>
  653. </div>
  654. </div>
  655. <!-- 对照:现状 -->
  656. <div class="phone-wrap dual" data-panel="compare-left">
  657. <div class="phone-label">左 · 现状</div>
  658. <div class="phone">
  659. <div class="nav">出库单</div>
  660. <div class="scroll">
  661. <div class="card">
  662. <div class="cell"><span class="label">单号</span><span class="value">CK20260719003</span></div>
  663. <div class="cell"><span class="label">状态</span><span class="value">进行中</span></div>
  664. <div class="cell"><span class="label">往来单位</span><span class="value">安徽某某化工…</span></div>
  665. <div class="cell"><span class="label">车牌</span><span class="value">皖H·A1234</span></div>
  666. <div class="cell"><span class="label">计划号</span><span class="value">YS20260719001</span></div>
  667. </div>
  668. <div class="card">
  669. <div class="card-title">产品实际数量</div>
  670. <div class="qty-old">
  671. <div class="qty-old__name">工业级尿素 <span class="qty-old__spec">46.4%</span></div>
  672. <div class="qty-old__plan">计划 32 dun ← 字典码未转义</div>
  673. <div class="qty-old__field">
  674. <span class="label">实际数量</span>
  675. <input class="qty-old__input" type="number" value="32" />
  676. </div>
  677. </div>
  678. </div>
  679. <div class="card">
  680. <div class="card-title">回执 / 备注</div>
  681. <div class="remark-area"><textarea placeholder="无取送货、无包装规格…"></textarea></div>
  682. </div>
  683. </div>
  684. <div class="footer"><button type="button">提交</button></div>
  685. </div>
  686. </div>
  687. <!-- 对照:提案 -->
  688. <div class="phone-wrap dual" data-panel="compare-right">
  689. <div class="phone-label">右 · 提案</div>
  690. <div class="phone">
  691. <div class="nav">出库单 · 现场回执</div>
  692. <div class="scroll">
  693. <div class="card">
  694. <div class="cell"><span class="label">业务类型</span><span class="value">出库</span></div>
  695. <div class="cell"><span class="label">日期</span><span class="value">2026-07-19</span></div>
  696. <div class="cell"><span class="label">往来单位</span><span class="value">安徽某某化工…</span></div>
  697. <div class="cell"><span class="label">车牌</span><span class="value">皖H·A1234</span></div>
  698. <div class="cell"><span class="label">计划号</span><span class="value">YS20260719001</span></div>
  699. </div>
  700. <div class="card">
  701. <div class="card-title">取货 / 送货</div>
  702. <div class="cell"><span class="label">取货</span><span class="value">迎江区某某路…</span></div>
  703. <div class="cell"><span class="label">送货</span><span class="value">包河区工业园…</span></div>
  704. </div>
  705. <div class="card">
  706. <div class="card-title">产品实际数量</div>
  707. <div class="product-card">
  708. <div class="product-card__head">
  709. <div class="product-card__name">工业级尿素</div>
  710. <span class="product-card__badge">1/2</span>
  711. </div>
  712. <div class="meta-grid">
  713. <div class="meta-item">
  714. <div class="meta-item__label">规格</div>
  715. <div class="meta-item__value">46.4%</div>
  716. </div>
  717. <div class="meta-item">
  718. <div class="meta-item__label">包装规格</div>
  719. <div class="meta-item__value">50kg/袋</div>
  720. </div>
  721. <div class="meta-item span-2">
  722. <div class="meta-item__label">计划数量</div>
  723. <div class="meta-item__value plan">32.000 吨</div>
  724. </div>
  725. </div>
  726. <div class="actual-box">
  727. <div class="actual-box__label"><strong>实际数量</strong></div>
  728. <div class="actual-box__row">
  729. <input class="actual-box__input" type="number" value="32" />
  730. <span class="actual-box__unit">吨</span>
  731. </div>
  732. </div>
  733. </div>
  734. </div>
  735. </div>
  736. <div class="footer"><button type="button">提交</button></div>
  737. </div>
  738. </div>
  739. </div>
  740. <div class="diff-note">
  741. <h2>本 Demo 相对现状的改动要点</h2>
  742. <ul>
  743. <li><strong>补回旧版现场链接信息:</strong>业务类型、日期、备注、取货信息(地址+导航+时间+注意事项)、送货信息、上次保存。</li>
  744. <li><strong>保留新版能力:</strong>产品行可填实际数量、整单回执上传、现场备注、提交。</li>
  745. <li><strong>产品实际数量美化:</strong>每产品独立卡片;规格 / 包装规格 / 计划数量网格展示;实际数量大字输入 + 单位后缀。</li>
  746. <li><strong>单位:</strong>展示字典标签「吨」,不展示字典码 <code>dun</code>(后端公共接口应对齐旧版 <code>crm_product_unit</code> 转义)。</li>
  747. <li><strong>包装规格:</strong>明细需带 <code>packageSpec</code>(当前出入库明细表可能缺该字段,需快照补齐或从计划产品回填)。</li>
  748. </ul>
  749. </div>
  750. <script>
  751. const phones = document.getElementById('phones')
  752. const buttons = document.querySelectorAll('.tabs button')
  753. const singles = document.querySelectorAll('.phone-wrap.single')
  754. const duals = document.querySelectorAll('.phone-wrap.dual')
  755. buttons.forEach((btn) => {
  756. btn.addEventListener('click', () => {
  757. buttons.forEach((b) => b.classList.remove('active'))
  758. btn.classList.add('active')
  759. const tab = btn.dataset.tab
  760. if (tab === 'compare') {
  761. phones.classList.add('show-dual')
  762. singles.forEach((el) => el.classList.remove('show'))
  763. return
  764. }
  765. phones.classList.remove('show-dual')
  766. singles.forEach((el) => {
  767. el.classList.toggle('show', el.dataset.panel === tab)
  768. })
  769. })
  770. })
  771. </script>
  772. </body>
  773. </html>