提交
This commit is contained in:
1 parent
9a1656505d
commit
124b15d094
7 files changed
+3046
No files matched your search
@@ -0,0 +1,334 @@
|
||||
/* 质检工单 · 同样本多工单 Tab 选型 Demo(Fresh Mint Token) */
|
||||
:root {
|
||||
--primary: #10b981;
|
||||
--primary-dark: #059669;
|
||||
--primary-bg: #ecfdf5;
|
||||
--text: #1e293b;
|
||||
--text-muted: #64748b;
|
||||
--border: #e2e8f0;
|
||||
--border-soft: #d9e8e2;
|
||||
--bg-page: #f8fafc;
|
||||
--surface: #fff;
|
||||
--radius: 10px;
|
||||
--radius-sm: 8px;
|
||||
--reception: #047857;
|
||||
--reception-bg: #ecfdf5;
|
||||
--reception-border: #a7f3d0;
|
||||
--production: #b45309;
|
||||
--production-bg: #fffbeb;
|
||||
--production-border: #fcd34d;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
font-family: Inter, -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
color: var(--text);
|
||||
background: var(--bg-page);
|
||||
}
|
||||
|
||||
.demo-banner {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 200;
|
||||
padding: 12px 24px;
|
||||
background: var(--surface);
|
||||
border-bottom: 1px solid var(--border);
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
|
||||
.demo-banner h1 {
|
||||
margin: 0;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.demo-banner p {
|
||||
margin: 4px 0 0;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
max-width: 760px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.demo-banner__actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.demo-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 32px;
|
||||
padding: 0 12px;
|
||||
border-radius: var(--radius-sm);
|
||||
border: 1px solid var(--border);
|
||||
background: var(--surface);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: var(--text);
|
||||
text-decoration: none;
|
||||
transition: border-color 0.15s, background 0.15s;
|
||||
}
|
||||
|
||||
.demo-link:hover {
|
||||
border-color: #a7f3d0;
|
||||
background: var(--primary-bg);
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.page-container {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 20px 24px 48px;
|
||||
}
|
||||
|
||||
.compare-stack {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 28px;
|
||||
}
|
||||
|
||||
.compare-block {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: var(--radius);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.compare-block__label {
|
||||
padding: 14px 18px;
|
||||
background: #fafafa;
|
||||
border-bottom: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.compare-block__label h2 {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.compare-block__label p {
|
||||
margin: 6px 0 0;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.variant-tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
padding: 0 8px;
|
||||
border-radius: 6px;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
.variant-tag--baseline {
|
||||
background: #f1f5f9;
|
||||
color: #475569;
|
||||
}
|
||||
|
||||
.variant-tag--rec {
|
||||
background: var(--primary-bg);
|
||||
color: var(--primary-dark);
|
||||
border: 1px solid #a7f3d0;
|
||||
}
|
||||
|
||||
.compare-block__body {
|
||||
padding: 16px;
|
||||
background: #f1f5f9;
|
||||
}
|
||||
|
||||
.pros-cons {
|
||||
margin-top: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.pro {
|
||||
color: #047857;
|
||||
}
|
||||
|
||||
.con {
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
/* ── 样本组卡片骨架 ── */
|
||||
.qc-sample-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
transition: border-color 0.15s ease, box-shadow 0.15s ease;
|
||||
}
|
||||
|
||||
.qc-sample-row:hover {
|
||||
border-color: #a8d4c4;
|
||||
box-shadow: 0 2px 8px rgba(4, 120, 87, 0.08);
|
||||
}
|
||||
|
||||
.qc-sample-row__ctx {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 8px 12px;
|
||||
padding: 12px 16px;
|
||||
background: linear-gradient(180deg, var(--primary-bg) 0%, #fff 100%);
|
||||
border-bottom: 1px solid #d1fae5;
|
||||
}
|
||||
|
||||
.qc-sample-row__idx {
|
||||
flex-shrink: 0;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
min-width: 20px;
|
||||
}
|
||||
|
||||
.qc-sample-row__code {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #1e293b;
|
||||
font-family: ui-monospace, Menlo, monospace;
|
||||
}
|
||||
|
||||
.qc-sample-row__sub {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.qc-sample-row__badge {
|
||||
flex-shrink: 0;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
padding: 2px 10px;
|
||||
border-radius: 999px;
|
||||
background: var(--primary-bg);
|
||||
color: #047857;
|
||||
border: 1px solid #d1fae5;
|
||||
}
|
||||
|
||||
/* 工单内容占位 */
|
||||
.qc-card-placeholder {
|
||||
padding: 14px 16px;
|
||||
background: #fafafa;
|
||||
border-top: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.qc-card-placeholder__head {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.qc-card-placeholder__no {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
font-family: ui-monospace, Menlo, monospace;
|
||||
}
|
||||
|
||||
.qc-card-placeholder__meta {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 8px;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.qc-card-placeholder__meta span strong {
|
||||
display: block;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: #94a3b8;
|
||||
}
|
||||
|
||||
.qc-card-placeholder__tasks {
|
||||
margin-top: 10px;
|
||||
padding: 10px 12px;
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* Tag 模拟 */
|
||||
.tag {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.tag--success {
|
||||
background: #ecfdf5;
|
||||
color: #047857;
|
||||
border-color: #a7f3d0;
|
||||
}
|
||||
|
||||
.tag--warning {
|
||||
background: #fffbeb;
|
||||
color: #b45309;
|
||||
border-color: #fcd34d;
|
||||
}
|
||||
|
||||
.tag--info {
|
||||
background: #f1f5f9;
|
||||
color: #475569;
|
||||
border-color: #e2e8f0;
|
||||
}
|
||||
|
||||
.tag--reception {
|
||||
background: var(--reception-bg);
|
||||
color: var(--reception);
|
||||
border-color: var(--reception-border);
|
||||
}
|
||||
|
||||
.tag--production {
|
||||
background: var(--production-bg);
|
||||
color: var(--production);
|
||||
border-color: var(--production-border);
|
||||
}
|
||||
|
||||
/* 通用 tab 按钮 reset */
|
||||
.tab-btn {
|
||||
font-family: inherit;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tab-btn:focus-visible {
|
||||
outline: 2px solid var(--primary);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,968 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>质检工单 · 同样本多工单 Tab 选型 · 对比总览</title>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link rel="stylesheet" href="_shared.css" />
|
||||
<style>
|
||||
/* ── V0 现网基线 ── */
|
||||
.v0-tabs {
|
||||
padding: 8px 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.v0-tabs__track {
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
padding: 6px;
|
||||
background: linear-gradient(180deg, var(--primary-bg) 0%, #fff 100%);
|
||||
border: 1px solid #d1fae5;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.v0-tabs__btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-height: 34px;
|
||||
padding: 8px 16px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
font-size: 12px;
|
||||
color: #1e293b;
|
||||
transition: background 0.15s, color 0.15s;
|
||||
}
|
||||
|
||||
.v0-tabs__btn:hover:not(.is-active) {
|
||||
background: #f1f5f9;
|
||||
}
|
||||
|
||||
.v0-tabs__btn.is-active {
|
||||
background: var(--primary);
|
||||
color: #fff;
|
||||
box-shadow: 0 1px 3px rgba(16, 185, 129, 0.28);
|
||||
}
|
||||
|
||||
.v0-tabs__btn:not(.is-active) .v0-source {
|
||||
color: #1e293b;
|
||||
background: #f1f5f9;
|
||||
}
|
||||
|
||||
.v0-tabs__btn.is-active .v0-source {
|
||||
color: #fff;
|
||||
background: rgb(255 255 255 / 22%);
|
||||
}
|
||||
|
||||
.v0-tabs__btn:not(.is-active) .tag {
|
||||
background: #f1f5f9;
|
||||
color: #1e293b;
|
||||
border-color: #e2e8f0;
|
||||
}
|
||||
|
||||
.v0-tabs__btn.is-active .tag {
|
||||
background: rgb(255 255 255 / 22%);
|
||||
color: #fff;
|
||||
border-color: rgb(255 255 255 / 35%);
|
||||
}
|
||||
|
||||
.v0-index {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
background: #e2e8f0;
|
||||
}
|
||||
|
||||
.v0-tabs__btn.is-active .v0-index {
|
||||
background: rgb(255 255 255 / 28%);
|
||||
}
|
||||
|
||||
.v0-source {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 1px 6px;
|
||||
border-radius: 4px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.v0-source__dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
}
|
||||
|
||||
.v0-no {
|
||||
font-family: ui-monospace, Menlo, monospace;
|
||||
}
|
||||
|
||||
/* ── V1 分类色保留 + 引导 ── */
|
||||
.v1-zone {
|
||||
padding: 10px 16px 8px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.v1-hint {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-bottom: 8px;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.v1-hint svg {
|
||||
flex-shrink: 0;
|
||||
color: var(--primary);
|
||||
}
|
||||
|
||||
.v1-hint strong {
|
||||
color: var(--primary-dark);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.v1-tabs__track {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.v1-tabs__btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
min-height: 40px;
|
||||
padding: 8px 14px;
|
||||
border: 2px solid var(--border);
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
font-size: 13px;
|
||||
color: var(--text);
|
||||
transition: border-color 0.15s, box-shadow 0.15s, transform 0.1s;
|
||||
}
|
||||
|
||||
.v1-tabs__btn:hover:not(.is-active) {
|
||||
border-color: #cbd5e1;
|
||||
box-shadow: 0 2px 6px rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
.v1-tabs__btn.is-active {
|
||||
border-color: var(--primary);
|
||||
background: var(--primary-bg);
|
||||
box-shadow: 0 0 0 1px var(--primary);
|
||||
}
|
||||
|
||||
.v1-tabs__btn.is-active[data-source='reception'] {
|
||||
border-color: var(--reception);
|
||||
background: var(--reception-bg);
|
||||
box-shadow: 0 0 0 1px var(--reception);
|
||||
}
|
||||
|
||||
.v1-tabs__btn.is-active[data-source='production'] {
|
||||
border-color: var(--production);
|
||||
background: var(--production-bg);
|
||||
box-shadow: 0 0 0 1px var(--production);
|
||||
}
|
||||
|
||||
.v1-tabs__btn:not(.is-active)::after {
|
||||
content: '点击查看';
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.v1-source-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
padding: 3px 8px;
|
||||
border-radius: 6px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.v1-source-badge--reception {
|
||||
background: var(--reception-bg);
|
||||
color: var(--reception);
|
||||
border: 1px solid var(--reception-border);
|
||||
}
|
||||
|
||||
.v1-source-badge--production {
|
||||
background: var(--production-bg);
|
||||
color: var(--production);
|
||||
border: 1px solid var(--production-border);
|
||||
}
|
||||
|
||||
/* ── V2 双卡片切换器 ── */
|
||||
.v2-zone {
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.v2-label {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.v2-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.v2-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.v2-card {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 12px 14px;
|
||||
border: 2px solid var(--border);
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
text-align: left;
|
||||
transition: border-color 0.15s, box-shadow 0.15s;
|
||||
}
|
||||
|
||||
.v2-card:hover:not(.is-active) {
|
||||
border-color: #cbd5e1;
|
||||
box-shadow: 0 2px 8px rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
.v2-card.is-active {
|
||||
box-shadow: 0 2px 10px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
.v2-card[data-source='reception'].is-active {
|
||||
border-color: var(--reception);
|
||||
background: linear-gradient(180deg, var(--reception-bg) 0%, #fff 40%);
|
||||
}
|
||||
|
||||
.v2-card[data-source='production'].is-active {
|
||||
border-color: var(--production);
|
||||
background: linear-gradient(180deg, var(--production-bg) 0%, #fff 40%);
|
||||
}
|
||||
|
||||
.v2-card:not(.is-active)::before {
|
||||
content: '点击切换';
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
padding: 2px 8px;
|
||||
border-radius: 999px;
|
||||
background: #f1f5f9;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.v2-card__top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.v2-card__icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.v2-card[data-source='reception'] .v2-card__icon {
|
||||
background: var(--reception-bg);
|
||||
color: var(--reception);
|
||||
}
|
||||
|
||||
.v2-card[data-source='production'] .v2-card__icon {
|
||||
background: var(--production-bg);
|
||||
color: var(--production);
|
||||
}
|
||||
|
||||
.v2-card__title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.v2-card__no {
|
||||
font-size: 12px;
|
||||
font-family: ui-monospace, Menlo, monospace;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.v2-card__foot {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* ── V3 流程步骤 ── */
|
||||
.v3-zone {
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.v3-steps {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
@media (max-width: 560px) {
|
||||
.v3-steps {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.v3-step__connector {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.v3-step {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
padding: 12px 14px;
|
||||
border: 2px solid var(--border);
|
||||
background: #fff;
|
||||
text-align: left;
|
||||
transition: border-color 0.15s, background 0.15s;
|
||||
}
|
||||
|
||||
.v3-step:first-child {
|
||||
border-radius: 10px 0 0 10px;
|
||||
}
|
||||
|
||||
.v3-step:last-child {
|
||||
border-radius: 0 10px 10px 0;
|
||||
}
|
||||
|
||||
.v3-step:hover:not(.is-active) {
|
||||
background: #fafafa;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.v3-step.is-active[data-source='reception'] {
|
||||
border-color: var(--reception);
|
||||
background: var(--reception-bg);
|
||||
}
|
||||
|
||||
.v3-step.is-active[data-source='production'] {
|
||||
border-color: var(--production);
|
||||
background: var(--production-bg);
|
||||
}
|
||||
|
||||
.v3-step:not(.is-active) {
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.v3-step:not(.is-active)::after {
|
||||
content: '点击切换至此工单';
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.v3-step__connector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
flex-shrink: 0;
|
||||
color: #94a3b8;
|
||||
background: #f1f5f9;
|
||||
border-top: 2px solid var(--border);
|
||||
border-bottom: 2px solid var(--border);
|
||||
}
|
||||
|
||||
.v3-step__num {
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.v3-step__name {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.v3-step__row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* ── V4 全宽分段控制器 ── */
|
||||
.v4-zone {
|
||||
padding: 10px 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.v4-segment {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
padding: 4px;
|
||||
gap: 4px;
|
||||
background: #e2e8f0;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.v4-segment__btn {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 10px 12px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
font-size: 13px;
|
||||
color: var(--text-muted);
|
||||
transition: background 0.15s, color 0.15s, box-shadow 0.15s;
|
||||
}
|
||||
|
||||
.v4-segment__btn:hover:not(.is-active) {
|
||||
background: rgb(255 255 255 / 60%);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.v4-segment__btn.is-active {
|
||||
background: #fff;
|
||||
color: var(--text);
|
||||
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.1);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.v4-segment__btn.is-active[data-source='reception'] .v4-segment__type {
|
||||
color: var(--reception);
|
||||
}
|
||||
|
||||
.v4-segment__btn.is-active[data-source='production'] .v4-segment__type {
|
||||
color: var(--production);
|
||||
}
|
||||
|
||||
.v4-segment__type {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.v4-segment__sub {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 11px;
|
||||
font-family: ui-monospace, Menlo, monospace;
|
||||
}
|
||||
|
||||
/* ── V5 左侧竖条 + 大标签(推荐) ── */
|
||||
.v5-zone {
|
||||
padding: 10px 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.v5-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.v5-prefix {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--text-muted);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.v5-tabs {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.v5-tab {
|
||||
display: inline-flex;
|
||||
align-items: stretch;
|
||||
min-height: 44px;
|
||||
padding: 0;
|
||||
border: 2px solid var(--border);
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
transition: border-color 0.15s, box-shadow 0.15s;
|
||||
}
|
||||
|
||||
.v5-tab:hover:not(.is-active) {
|
||||
border-color: #94a3b8;
|
||||
box-shadow: 0 2px 6px rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
.v5-tab.is-active {
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 0 0 1px var(--primary);
|
||||
}
|
||||
|
||||
.v5-tab.is-active[data-source='reception'] {
|
||||
border-color: var(--reception);
|
||||
box-shadow: 0 0 0 1px var(--reception);
|
||||
}
|
||||
|
||||
.v5-tab.is-active[data-source='production'] {
|
||||
border-color: var(--production);
|
||||
box-shadow: 0 0 0 1px var(--production);
|
||||
}
|
||||
|
||||
.v5-tab__accent {
|
||||
width: 5px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.v5-tab[data-source='reception'] .v5-tab__accent {
|
||||
background: var(--reception);
|
||||
}
|
||||
|
||||
.v5-tab[data-source='production'] .v5-tab__accent {
|
||||
background: var(--production);
|
||||
}
|
||||
|
||||
.v5-tab__body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 2px;
|
||||
padding: 8px 14px 8px 10px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.v5-tab__type {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.v5-tab__meta {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 11px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.v5-tab__meta code {
|
||||
font-family: ui-monospace, Menlo, monospace;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.v5-tab:not(.is-active) .v5-tab__hint {
|
||||
font-size: 10px;
|
||||
color: var(--primary-dark);
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="demo-banner">
|
||||
<div>
|
||||
<h1>质检工单 · 细胞存储 · 同样本多工单 Tab 选型</h1>
|
||||
<p>
|
||||
场景:同一样本编码下存在<strong>样本接收</strong>与<strong>生产过程</strong>两条质检工单,需在卡片内切换查看。
|
||||
下方 6 套方案均可点击交互,请对比哪套最能传达「可切换、类别不同」。
|
||||
</p>
|
||||
</div>
|
||||
<div class="demo-banner__actions">
|
||||
<a class="demo-link" href="index.html">← 索引</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="page-container">
|
||||
<div class="compare-stack">
|
||||
<!-- V0 -->
|
||||
<section class="compare-block" data-variant="v0">
|
||||
<div class="compare-block__label">
|
||||
<h2>
|
||||
<span class="variant-tag variant-tag--baseline">V0</span>
|
||||
现网基线(当前实现)
|
||||
</h2>
|
||||
<p>胶囊 Tab 内嵌序号 + 来源标签 + 工单号 + 状态;未选中时来源与状态均灰化,类别差异不明显。</p>
|
||||
<div class="pros-cons">
|
||||
<div class="con">✗ 未选中 Tab 全灰,样本接收 / 生产过程难以区分</div>
|
||||
<div class="con">✗ 交互感弱,易被当成静态信息条</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="compare-block__body" id="block-v0"></div>
|
||||
</section>
|
||||
|
||||
<!-- V1 -->
|
||||
<section class="compare-block" data-variant="v1">
|
||||
<div class="compare-block__label">
|
||||
<h2>
|
||||
<span class="variant-tag">V1</span>
|
||||
分类色保留 + 引导文案 +「点击查看」
|
||||
</h2>
|
||||
<p>渐进改良:保留横向 Tab 布局,未选中仍保留绿/琥珀来源色,并加一行引导 + 未选中 Tab 后缀「点击查看」。</p>
|
||||
<div class="pros-cons">
|
||||
<div class="pro">✓ 改动量小,与现网结构最接近</div>
|
||||
<div class="pro">✓ 类别色始终可见</div>
|
||||
<div class="con">✗ 引导文案熟悉后可能略冗余</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="compare-block__body" id="block-v1"></div>
|
||||
</section>
|
||||
|
||||
<!-- V5 推荐放前面一点 - actually keep order logical -->
|
||||
|
||||
<!-- V2 -->
|
||||
<section class="compare-block" data-variant="v2">
|
||||
<div class="compare-block__label">
|
||||
<h2>
|
||||
<span class="variant-tag variant-tag--rec">推荐</span>
|
||||
<span class="variant-tag">V2</span>
|
||||
双卡片切换器
|
||||
</h2>
|
||||
<p>两条工单并排展示为可点击卡片,图标 + 大标题区分来源,未选中角标「点击切换」,选中侧渐变高亮。</p>
|
||||
<div class="pros-cons">
|
||||
<div class="pro">✓ 可点击性最强,两类工单一眼可辨</div>
|
||||
<div class="pro">✓ 移动端可纵向堆叠</div>
|
||||
<div class="con">✗ 占用垂直空间略多</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="compare-block__body" id="block-v2"></div>
|
||||
</section>
|
||||
|
||||
<!-- V3 -->
|
||||
<section class="compare-block" data-variant="v3">
|
||||
<div class="compare-block__label">
|
||||
<h2><span class="variant-tag">V3</span> 流程步骤条(接收 → 生产)</h2>
|
||||
<p>强调业务先后顺序:样本接收在前、生产过程在后,中间箭头连接;未选中步骤提示「点击切换至此工单」。</p>
|
||||
<div class="pros-cons">
|
||||
<div class="pro">✓ 传达「同一流程两阶段」的业务语义</div>
|
||||
<div class="con">✗ 若未来出现 3+ 条工单,横向会拥挤</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="compare-block__body" id="block-v3"></div>
|
||||
</section>
|
||||
|
||||
<!-- V4 -->
|
||||
<section class="compare-block" data-variant="v4">
|
||||
<div class="compare-block__label">
|
||||
<h2><span class="variant-tag">V4</span> 全宽分段控制器(iOS Segmented)</h2>
|
||||
<p>类似系统分段控件,占满卡片宽度;选中项白底浮起,类型名加粗,下方显示工单号与状态。</p>
|
||||
<div class="pros-cons">
|
||||
<div class="pro">✓ 切换控件形态 familiar,点击区域大</div>
|
||||
<div class="con">✗ 类别色仅体现在选中态文字,未选中时仍偏中性</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="compare-block__body" id="block-v4"></div>
|
||||
</section>
|
||||
|
||||
<!-- V5 -->
|
||||
<section class="compare-block" data-variant="v5">
|
||||
<div class="compare-block__label">
|
||||
<h2>
|
||||
<span class="variant-tag variant-tag--rec">推荐</span>
|
||||
<span class="variant-tag">V5</span>
|
||||
左侧色条 + 大标签 Tab
|
||||
</h2>
|
||||
<p>
|
||||
「切换工单:」前缀 + 带左侧竖条(绿=接收、琥珀=生产)的大按钮;未选中显示「点此查看」微提示,选中展示完整工单号与状态。
|
||||
</p>
|
||||
<div class="pros-cons">
|
||||
<div class="pro">✓ 类别色条 + 44px 触控高度,可发现性与无障碍兼顾</div>
|
||||
<div class="pro">✓ 信息密度适中,适合 2~3 条工单</div>
|
||||
<div class="con">✗ 比 V0 略占高度</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="compare-block__body" id="block-v5"></div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const MOCK = {
|
||||
sampleCode: 'YB-2025-0618-0042',
|
||||
subtitle: '张三 · 间充质干细胞 · 5×10⁶/支',
|
||||
workOrders: [
|
||||
{
|
||||
id: 'wo-reception',
|
||||
source: 'reception',
|
||||
label: '样本接收',
|
||||
no: 'QC-IN-20250618-0012',
|
||||
status: 'ywc',
|
||||
statusLabel: '已完成',
|
||||
statusClass: 'tag--success'
|
||||
},
|
||||
{
|
||||
id: 'wo-production',
|
||||
source: 'production',
|
||||
label: '生产过程',
|
||||
no: 'QC-IN-20250620-0038',
|
||||
status: 'ypz',
|
||||
statusLabel: '已配置',
|
||||
statusClass: 'tag--warning'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const ICONS = {
|
||||
reception: `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/><polyline points="3.27 6.96 12 12.01 20.73 6.96"/><line x1="12" y1="22.08" x2="12" y2="12"/></svg>`,
|
||||
production: `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 1v4M12 19v4M4.22 4.22l2.83 2.83M16.95 16.95l2.83 2.83M1 12h4M19 12h4M4.22 19.78l2.83-2.83M16.95 7.05l2.83-2.83"/></svg>`
|
||||
}
|
||||
|
||||
function ctxHeader() {
|
||||
return `
|
||||
<div class="qc-sample-row__ctx">
|
||||
<span class="qc-sample-row__idx">1</span>
|
||||
<span class="qc-sample-row__code">${MOCK.sampleCode}</span>
|
||||
<span class="qc-sample-row__sub">${MOCK.subtitle}</span>
|
||||
<span class="qc-sample-row__badge">${MOCK.workOrders.length} 条质检</span>
|
||||
</div>`
|
||||
}
|
||||
|
||||
function cardPlaceholder(wo) {
|
||||
return `
|
||||
<div class="qc-card-placeholder">
|
||||
<div class="qc-card-placeholder__head">
|
||||
<span class="qc-card-placeholder__no">${wo.no}</span>
|
||||
<span class="tag ${wo.statusClass}">${wo.statusLabel}</span>
|
||||
<span class="tag tag--${wo.source}">${wo.label}</span>
|
||||
</div>
|
||||
<div class="qc-card-placeholder__meta">
|
||||
<span><strong>触发来源</strong>${wo.label}</span>
|
||||
<span><strong>细胞类型</strong>间充质干细胞</span>
|
||||
<span><strong>创建时间</strong>2025-06-18 14:32</span>
|
||||
</div>
|
||||
<div class="qc-card-placeholder__tasks">▼ 质检任务列表(当前选中:${wo.label})</div>
|
||||
</div>`
|
||||
}
|
||||
|
||||
function wrapSampleRow(inner, activeWo) {
|
||||
return `
|
||||
<article class="qc-sample-row">
|
||||
${ctxHeader()}
|
||||
${inner}
|
||||
${cardPlaceholder(activeWo)}
|
||||
</article>`
|
||||
}
|
||||
|
||||
/* ── V0 ── */
|
||||
function renderV0(activeId) {
|
||||
const active = MOCK.workOrders.find((w) => w.id === activeId)
|
||||
const tabs = MOCK.workOrders
|
||||
.map(
|
||||
(wo, i) => `
|
||||
<button type="button" class="v0-tabs__btn tab-btn ${wo.id === activeId ? 'is-active' : ''}"
|
||||
data-id="${wo.id}" role="tab" aria-selected="${wo.id === activeId}">
|
||||
<span class="v0-index">${i + 1}</span>
|
||||
<span class="v0-source"><span class="v0-source__dot"></span>${wo.label}</span>
|
||||
<span class="v0-no">${wo.no}</span>
|
||||
<span class="tag ${wo.statusClass}">${wo.statusLabel}</span>
|
||||
</button>`
|
||||
)
|
||||
.join('')
|
||||
return wrapSampleRow(
|
||||
`<div class="v0-tabs"><div class="v0-tabs__track" role="tablist">${tabs}</div></div>`,
|
||||
active
|
||||
)
|
||||
}
|
||||
|
||||
/* ── V1 ── */
|
||||
function renderV1(activeId) {
|
||||
const active = MOCK.workOrders.find((w) => w.id === activeId)
|
||||
const tabs = MOCK.workOrders
|
||||
.map(
|
||||
(wo) => `
|
||||
<button type="button" class="v1-tabs__btn tab-btn ${wo.id === activeId ? 'is-active' : ''}"
|
||||
data-id="${wo.id}" data-source="${wo.source}" role="tab">
|
||||
<span class="v1-source-badge v1-source-badge--${wo.source}">${wo.label}</span>
|
||||
<span style="font-family:ui-monospace,Menlo,monospace;font-size:12px">${wo.no}</span>
|
||||
<span class="tag ${wo.statusClass}">${wo.statusLabel}</span>
|
||||
</button>`
|
||||
)
|
||||
.join('')
|
||||
return wrapSampleRow(
|
||||
`<div class="v1-zone">
|
||||
<div class="v1-hint">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>
|
||||
同一样本含 <strong>${MOCK.workOrders.length} 条质检工单</strong>,点击下方切换查看
|
||||
</div>
|
||||
<div class="v1-tabs__track" role="tablist">${tabs}</div>
|
||||
</div>`,
|
||||
active
|
||||
)
|
||||
}
|
||||
|
||||
/* ── V2 ── */
|
||||
function renderV2(activeId) {
|
||||
const active = MOCK.workOrders.find((w) => w.id === activeId)
|
||||
const cards = MOCK.workOrders
|
||||
.map(
|
||||
(wo) => `
|
||||
<button type="button" class="v2-card tab-btn ${wo.id === activeId ? 'is-active' : ''}"
|
||||
data-id="${wo.id}" data-source="${wo.source}">
|
||||
<div class="v2-card__top">
|
||||
<span class="v2-card__icon">${ICONS[wo.source]}</span>
|
||||
<div>
|
||||
<div class="v2-card__title">${wo.label}</div>
|
||||
<div class="v2-card__no">${wo.no}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="v2-card__foot">
|
||||
<span class="tag ${wo.statusClass}">${wo.statusLabel}</span>
|
||||
</div>
|
||||
</button>`
|
||||
)
|
||||
.join('')
|
||||
return wrapSampleRow(
|
||||
`<div class="v2-zone">
|
||||
<div class="v2-label">选择要查看的质检工单</div>
|
||||
<div class="v2-grid">${cards}</div>
|
||||
</div>`,
|
||||
active
|
||||
)
|
||||
}
|
||||
|
||||
/* ── V3 ── */
|
||||
function renderV3(activeId) {
|
||||
const active = MOCK.workOrders.find((w) => w.id === activeId)
|
||||
const [wo1, wo2] = MOCK.workOrders
|
||||
return wrapSampleRow(
|
||||
`<div class="v3-zone">
|
||||
<div class="v3-steps" role="tablist">
|
||||
<button type="button" class="v3-step tab-btn ${wo1.id === activeId ? 'is-active' : ''}"
|
||||
data-id="${wo1.id}" data-source="${wo1.source}" role="tab">
|
||||
<span class="v3-step__num">阶段 1</span>
|
||||
<span class="v3-step__name">${wo1.label}</span>
|
||||
<span class="v3-step__row">
|
||||
<code style="font-size:11px">${wo1.no}</code>
|
||||
<span class="tag ${wo1.statusClass}">${wo1.statusLabel}</span>
|
||||
</span>
|
||||
</button>
|
||||
<div class="v3-step__connector" aria-hidden="true">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
|
||||
</div>
|
||||
<button type="button" class="v3-step tab-btn ${wo2.id === activeId ? 'is-active' : ''}"
|
||||
data-id="${wo2.id}" data-source="${wo2.source}" role="tab">
|
||||
<span class="v3-step__num">阶段 2</span>
|
||||
<span class="v3-step__name">${wo2.label}</span>
|
||||
<span class="v3-step__row">
|
||||
<code style="font-size:11px">${wo2.no}</code>
|
||||
<span class="tag ${wo2.statusClass}">${wo2.statusLabel}</span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>`,
|
||||
active
|
||||
)
|
||||
}
|
||||
|
||||
/* ── V4 ── */
|
||||
function renderV4(activeId) {
|
||||
const active = MOCK.workOrders.find((w) => w.id === activeId)
|
||||
const btns = MOCK.workOrders
|
||||
.map(
|
||||
(wo) => `
|
||||
<button type="button" class="v4-segment__btn tab-btn ${wo.id === activeId ? 'is-active' : ''}"
|
||||
data-id="${wo.id}" data-source="${wo.source}" role="tab">
|
||||
<span class="v4-segment__type">${wo.label}</span>
|
||||
<span class="v4-segment__sub">
|
||||
<span>${wo.no.slice(-8)}</span>
|
||||
<span class="tag ${wo.statusClass}" style="height:18px;padding:0 6px;font-size:10px">${wo.statusLabel}</span>
|
||||
</span>
|
||||
</button>`
|
||||
)
|
||||
.join('')
|
||||
return wrapSampleRow(`<div class="v4-zone"><div class="v4-segment" role="tablist">${btns}</div></div>`, active)
|
||||
}
|
||||
|
||||
/* ── V5 ── */
|
||||
function renderV5(activeId) {
|
||||
const active = MOCK.workOrders.find((w) => w.id === activeId)
|
||||
const tabs = MOCK.workOrders
|
||||
.map(
|
||||
(wo) => `
|
||||
<button type="button" class="v5-tab tab-btn ${wo.id === activeId ? 'is-active' : ''}"
|
||||
data-id="${wo.id}" data-source="${wo.source}" role="tab">
|
||||
<span class="v5-tab__accent"></span>
|
||||
<span class="v5-tab__body">
|
||||
<span class="v5-tab__type">${wo.label}</span>
|
||||
<span class="v5-tab__meta">
|
||||
${wo.id === activeId ? `<code>${wo.no}</code><span class="tag ${wo.statusClass}">${wo.statusLabel}</span>` : `<span class="v5-tab__hint">点此查看 →</span>`}
|
||||
</span>
|
||||
</span>
|
||||
</button>`
|
||||
)
|
||||
.join('')
|
||||
return wrapSampleRow(
|
||||
`<div class="v5-zone">
|
||||
<div class="v5-row">
|
||||
<span class="v5-prefix">切换工单</span>
|
||||
<div class="v5-tabs" role="tablist">${tabs}</div>
|
||||
</div>
|
||||
</div>`,
|
||||
active
|
||||
)
|
||||
}
|
||||
|
||||
const VARIANTS = {
|
||||
v0: { render: renderV0, default: 'wo-reception' },
|
||||
v1: { render: renderV1, default: 'wo-reception' },
|
||||
v2: { render: renderV2, default: 'wo-reception' },
|
||||
v3: { render: renderV3, default: 'wo-reception' },
|
||||
v4: { render: renderV4, default: 'wo-reception' },
|
||||
v5: { render: renderV5, default: 'wo-reception' }
|
||||
}
|
||||
|
||||
const state = {}
|
||||
Object.keys(VARIANTS).forEach((k) => {
|
||||
state[k] = VARIANTS[k].default
|
||||
})
|
||||
|
||||
function mountVariant(key) {
|
||||
const el = document.getElementById(`block-${key}`)
|
||||
el.innerHTML = VARIANTS[key].render(state[key])
|
||||
el.querySelectorAll('[data-id]').forEach((btn) => {
|
||||
btn.addEventListener('click', () => {
|
||||
state[key] = btn.dataset.id
|
||||
mountVariant(key)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Object.keys(VARIANTS).forEach(mountVariant)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,422 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>质检工单 · 独立胶囊 Tab Demo</title>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link rel="stylesheet" href="_shared.css" />
|
||||
<style>
|
||||
/* ── 共享:胶囊按钮内容(对齐现网 QcWorkOrderSampleGroup) ── */
|
||||
.pill-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-height: 34px;
|
||||
padding: 8px 16px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
font-family: inherit;
|
||||
color: #1e293b;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
transition:
|
||||
background 0.15s,
|
||||
color 0.15s,
|
||||
border-color 0.15s,
|
||||
box-shadow 0.15s;
|
||||
}
|
||||
|
||||
.pill-btn:focus-visible {
|
||||
outline: 2px solid #10b981;
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.pill-index {
|
||||
flex-shrink: 0;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
background: #e2e8f0;
|
||||
}
|
||||
|
||||
.pill-source {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 1px 6px;
|
||||
border-radius: 4px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
background: #f1f5f9;
|
||||
}
|
||||
|
||||
.pill-source--reception {
|
||||
color: var(--reception);
|
||||
background: var(--reception-bg);
|
||||
}
|
||||
|
||||
.pill-source--production {
|
||||
color: var(--production);
|
||||
background: var(--production-bg);
|
||||
}
|
||||
|
||||
.pill-source__dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: currentColor;
|
||||
}
|
||||
|
||||
.pill-no {
|
||||
font-family: ui-monospace, Menlo, monospace;
|
||||
}
|
||||
|
||||
.pill-btn.is-active {
|
||||
color: #fff;
|
||||
background: var(--primary);
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 2px 6px rgba(16, 185, 129, 0.28);
|
||||
}
|
||||
|
||||
.pill-btn.is-active .pill-index {
|
||||
color: #fff;
|
||||
background: rgb(255 255 255 / 28%);
|
||||
}
|
||||
|
||||
.pill-btn.is-active .pill-source,
|
||||
.pill-btn.is-active .pill-source--reception,
|
||||
.pill-btn.is-active .pill-source--production {
|
||||
color: #fff;
|
||||
background: rgb(255 255 255 / 22%);
|
||||
}
|
||||
|
||||
.pill-btn.is-active .tag {
|
||||
background: rgb(255 255 255 / 22%);
|
||||
color: #fff;
|
||||
border-color: rgb(255 255 255 / 35%);
|
||||
}
|
||||
|
||||
.pill-btn:not(.is-active) .tag {
|
||||
background: #f1f5f9;
|
||||
color: #1e293b;
|
||||
border-color: #e2e8f0;
|
||||
}
|
||||
|
||||
/* ── A · 现网:轨道内连体 ── */
|
||||
.grouped-zone {
|
||||
padding: 8px 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.grouped-track {
|
||||
display: inline-flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
padding: 6px;
|
||||
background: linear-gradient(180deg, var(--primary-bg) 0%, #fff 100%);
|
||||
border: 1px solid #d1fae5;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.grouped-track .pill-btn {
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.grouped-track .pill-btn:hover:not(.is-active) {
|
||||
background: #f1f5f9;
|
||||
}
|
||||
|
||||
/* ── B/C/D · 独立胶囊 ── */
|
||||
.indep-zone {
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid var(--border);
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.indep-zone__hint {
|
||||
margin-bottom: 10px;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.indep-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.indep-row--gap-md {
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.indep-row--gap-lg {
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.indep-row--gap-xl {
|
||||
gap: 32px;
|
||||
}
|
||||
|
||||
/* 每个胶囊独立边框 + 白底 */
|
||||
.indep-row .pill-btn {
|
||||
border: 2px solid #e2e8f0;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
.indep-row .pill-btn:hover:not(.is-active) {
|
||||
border-color: #cbd5e1;
|
||||
box-shadow: 0 2px 8px rgba(15, 23, 42, 0.08);
|
||||
}
|
||||
|
||||
/* 未选中时按来源保留边框色 */
|
||||
.indep-row .pill-btn[data-source='reception']:not(.is-active) {
|
||||
border-color: var(--reception-border);
|
||||
}
|
||||
|
||||
.indep-row .pill-btn[data-source='production']:not(.is-active) {
|
||||
border-color: var(--production-border);
|
||||
}
|
||||
|
||||
.indep-row .pill-btn[data-source='reception']:not(.is-active):hover {
|
||||
border-color: var(--reception);
|
||||
background: var(--reception-bg);
|
||||
}
|
||||
|
||||
.indep-row .pill-btn[data-source='production']:not(.is-active):hover {
|
||||
border-color: var(--production);
|
||||
background: var(--production-bg);
|
||||
}
|
||||
|
||||
/* D · 独立 + 更大胶囊 */
|
||||
.indep-row--large .pill-btn {
|
||||
min-height: 40px;
|
||||
padding: 10px 18px;
|
||||
font-size: 13px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
.indep-row--large .pill-source {
|
||||
font-size: 12px;
|
||||
padding: 2px 8px;
|
||||
}
|
||||
|
||||
.gap-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: 22px;
|
||||
padding: 0 8px;
|
||||
margin-left: 8px;
|
||||
border-radius: 6px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
background: #f1f5f9;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header class="demo-banner">
|
||||
<div>
|
||||
<h1>独立胶囊 Tab · 对比 Demo</h1>
|
||||
<p>
|
||||
在现网胶囊内容结构不变的前提下,将每个 Tab 从<strong>轨道连体</strong>改为<strong>独立胶囊</strong>,并加大间距。
|
||||
下方 A 为现网对照,B/C/D 为独立方案(间距 16 / 24 / 32px,均可点击切换)。
|
||||
</p>
|
||||
</div>
|
||||
<div class="demo-banner__actions">
|
||||
<a class="demo-link" href="index.html">← 索引</a>
|
||||
<a class="demo-link" href="compare-all-v2.html">第二组方案</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="page-container">
|
||||
<div class="compare-stack">
|
||||
<section class="compare-block">
|
||||
<div class="compare-block__label">
|
||||
<h2>
|
||||
<span class="variant-tag variant-tag--baseline">A</span>
|
||||
现网 · 轨道内连体(对照)
|
||||
</h2>
|
||||
<p>多个 Tab 包在同一 <code>panel-pill-tabs__track</code> 绿底容器内,胶囊之间 gap 10px,视觉上像一组。</p>
|
||||
</div>
|
||||
<div class="compare-block__body" id="block-a"></div>
|
||||
</section>
|
||||
|
||||
<section class="compare-block">
|
||||
<div class="compare-block__label">
|
||||
<h2>
|
||||
<span class="variant-tag variant-tag--rec">推荐</span>
|
||||
<span class="variant-tag">B</span>
|
||||
独立胶囊 · 间距 16px
|
||||
</h2>
|
||||
<p>去掉外层轨道,每个 Tab 自带白底 + 2px 边框 + 轻阴影;未选中按来源保留绿/琥珀边框色。</p>
|
||||
</div>
|
||||
<div class="compare-block__body" id="block-b"></div>
|
||||
</section>
|
||||
|
||||
<section class="compare-block">
|
||||
<div class="compare-block__label">
|
||||
<h2><span class="variant-tag">C</span> 独立胶囊 · 间距 24px</h2>
|
||||
<p>同 B,胶囊间距加大到 24px,分离感更强。</p>
|
||||
</div>
|
||||
<div class="compare-block__body" id="block-c"></div>
|
||||
</section>
|
||||
|
||||
<section class="compare-block">
|
||||
<div class="compare-block__label">
|
||||
<h2><span class="variant-tag">D</span> 独立胶囊 · 间距 32px + 略放大</h2>
|
||||
<p>间距 32px,胶囊 min-height 40px、圆角 12px,点击区域更大。</p>
|
||||
</div>
|
||||
<div class="compare-block__body" id="block-d"></div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const MOCK = {
|
||||
sampleCode: 'YB-2025-0618-0042',
|
||||
subtitle: '张三 · 间充质干细胞 · 5×10⁶/支',
|
||||
workOrders: [
|
||||
{
|
||||
id: 'wo-reception',
|
||||
source: 'reception',
|
||||
label: '样本接收',
|
||||
no: 'QC-IN-20250618-0012',
|
||||
statusLabel: '已完成',
|
||||
statusClass: 'tag--success'
|
||||
},
|
||||
{
|
||||
id: 'wo-production',
|
||||
source: 'production',
|
||||
label: '生产过程',
|
||||
no: 'QC-IN-20250620-0038',
|
||||
statusLabel: '已配置',
|
||||
statusClass: 'tag--warning'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
function ctxHeader() {
|
||||
return `
|
||||
<div class="qc-sample-row__ctx">
|
||||
<span class="qc-sample-row__idx">1</span>
|
||||
<span class="qc-sample-row__code">${MOCK.sampleCode}</span>
|
||||
<span class="qc-sample-row__sub">${MOCK.subtitle}</span>
|
||||
<span class="qc-sample-row__badge">${MOCK.workOrders.length} 条质检</span>
|
||||
</div>`
|
||||
}
|
||||
|
||||
function pillBtn(wo, i, activeId) {
|
||||
const active = wo.id === activeId
|
||||
return `
|
||||
<button type="button" class="pill-btn tab-btn ${active ? 'is-active' : ''}"
|
||||
data-id="${wo.id}" data-source="${wo.source}" role="tab" aria-selected="${active}">
|
||||
<span class="pill-index">${i + 1}</span>
|
||||
<span class="pill-source pill-source--${wo.source}">
|
||||
<span class="pill-source__dot"></span>${wo.label}
|
||||
</span>
|
||||
<span class="pill-no">${wo.no}</span>
|
||||
<span class="tag ${wo.statusClass}">${wo.statusLabel}</span>
|
||||
</button>`
|
||||
}
|
||||
|
||||
function cardPlaceholder(wo) {
|
||||
return `
|
||||
<div class="qc-card-placeholder">
|
||||
<div class="qc-card-placeholder__head">
|
||||
<span class="qc-card-placeholder__no">${wo.no}</span>
|
||||
<span class="tag ${wo.statusClass}">${wo.statusLabel}</span>
|
||||
<span class="tag tag--${wo.source}">${wo.label}</span>
|
||||
</div>
|
||||
<div class="qc-card-placeholder__tasks">▼ 质检任务列表(${wo.label})</div>
|
||||
</div>`
|
||||
}
|
||||
|
||||
function wrap(tabsHtml, activeId) {
|
||||
const active = MOCK.workOrders.find((w) => w.id === activeId)
|
||||
return `
|
||||
<article class="qc-sample-row">
|
||||
${ctxHeader()}
|
||||
${tabsHtml}
|
||||
${cardPlaceholder(active)}
|
||||
</article>`
|
||||
}
|
||||
|
||||
function renderGrouped(activeId) {
|
||||
const pills = MOCK.workOrders.map((wo, i) => pillBtn(wo, i, activeId)).join('')
|
||||
return wrap(
|
||||
`<div class="grouped-zone">
|
||||
<div class="grouped-track" role="tablist" aria-label="同样本质检工单">${pills}</div>
|
||||
</div>`,
|
||||
activeId
|
||||
)
|
||||
}
|
||||
|
||||
function renderIndependent(activeId, gapClass, extraRowClass, hint) {
|
||||
const pills = MOCK.workOrders.map((wo, i) => pillBtn(wo, i, activeId)).join('')
|
||||
const gapLabel = gapClass.replace('indep-row--gap-', '') + 'px'
|
||||
return wrap(
|
||||
`<div class="indep-zone">
|
||||
${hint ? `<div class="indep-zone__hint">${hint}</div>` : ''}
|
||||
<div class="indep-row ${gapClass} ${extraRowClass || ''}" role="tablist" aria-label="同样本质检工单">
|
||||
${pills}
|
||||
</div>
|
||||
</div>`,
|
||||
activeId
|
||||
)
|
||||
}
|
||||
|
||||
const BLOCKS = {
|
||||
a: { render: (id) => renderGrouped(id), default: 'wo-reception' },
|
||||
b: {
|
||||
render: (id) =>
|
||||
renderIndependent(id, 'indep-row--gap-md', '', '每个胶囊独立展示,间距 16px'),
|
||||
default: 'wo-reception'
|
||||
},
|
||||
c: {
|
||||
render: (id) =>
|
||||
renderIndependent(id, 'indep-row--gap-lg', '', '每个胶囊独立展示,间距 24px'),
|
||||
default: 'wo-reception'
|
||||
},
|
||||
d: {
|
||||
render: (id) =>
|
||||
renderIndependent(
|
||||
id,
|
||||
'indep-row--gap-xl',
|
||||
'indep-row--large',
|
||||
'每个胶囊独立展示,间距 32px,尺寸略放大'
|
||||
),
|
||||
default: 'wo-reception'
|
||||
}
|
||||
}
|
||||
|
||||
const state = Object.fromEntries(Object.entries(BLOCKS).map(([k, v]) => [k, v.default]))
|
||||
|
||||
function mount(key) {
|
||||
const el = document.getElementById(`block-${key}`)
|
||||
el.innerHTML = BLOCKS[key].render(state[key])
|
||||
el.querySelectorAll('[data-id]').forEach((btn) => {
|
||||
btn.addEventListener('click', () => {
|
||||
state[key] = btn.dataset.id
|
||||
mount(key)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
Object.keys(BLOCKS).forEach(mount)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,263 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>质检工单 · 同样本多工单 Tab 选型 · 索引</title>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link rel="stylesheet" href="_shared.css" />
|
||||
<style>
|
||||
.index-hero {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 32px 24px 12px;
|
||||
}
|
||||
|
||||
.index-hero h1 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.index-hero p {
|
||||
margin: 0;
|
||||
color: var(--text-muted);
|
||||
max-width: 720px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.index-cta {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 8px 24px 12px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.index-cta a {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
height: 44px;
|
||||
padding: 0 20px;
|
||||
border-radius: 10px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
text-decoration: none;
|
||||
transition: background 0.15s;
|
||||
}
|
||||
|
||||
.index-cta a.primary {
|
||||
background: var(--primary);
|
||||
color: #fff;
|
||||
box-shadow: 0 2px 8px rgba(16, 185, 129, 0.25);
|
||||
}
|
||||
|
||||
.index-cta a.primary:hover {
|
||||
background: var(--primary-dark);
|
||||
}
|
||||
|
||||
.index-cta a.secondary {
|
||||
background: var(--surface);
|
||||
color: var(--text);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
|
||||
.index-cta a.secondary:hover {
|
||||
border-color: #a7f3d0;
|
||||
background: var(--primary-bg);
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.batch-section {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 16px 24px 8px;
|
||||
}
|
||||
|
||||
.batch-section h2 {
|
||||
margin: 0 0 4px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.batch-section p {
|
||||
margin: 0 0 12px;
|
||||
font-size: 13px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.index-grid {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 0 24px 32px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.index-card {
|
||||
background: var(--surface);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 12px;
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
.index-card h3 {
|
||||
margin: 0 0 6px;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
.index-card p {
|
||||
margin: 0;
|
||||
font-size: 13px;
|
||||
color: var(--text-muted);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.index-card .tag {
|
||||
display: inline-block;
|
||||
margin-top: 12px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 6px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
background: #f1f5f9;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.index-card .tag--rec {
|
||||
background: var(--primary-bg);
|
||||
color: var(--primary-dark);
|
||||
border: 1px solid #a7f3d0;
|
||||
}
|
||||
|
||||
.index-card .tag--new {
|
||||
background: #fffbeb;
|
||||
color: #b45309;
|
||||
border: 1px solid #fcd34d;
|
||||
}
|
||||
|
||||
.context-box {
|
||||
max-width: 960px;
|
||||
margin: 0 auto 8px;
|
||||
padding: 0 24px;
|
||||
}
|
||||
|
||||
.context-box-inner {
|
||||
padding: 14px 16px;
|
||||
background: #fffbeb;
|
||||
border: 1px solid #fcd34d;
|
||||
border-radius: 10px;
|
||||
font-size: 13px;
|
||||
color: #92400e;
|
||||
line-height: 1.55;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="index-hero">
|
||||
<h1>质检工单 · 细胞存储 · 同样本多工单 Tab 选型</h1>
|
||||
<p>
|
||||
针对 <code>QcWorkOrderSampleGroup.vue</code> 中「同一样本下样本接收 + 生产过程两条工单」的切换区域。
|
||||
共两组 HTML 原型,均可点击交互。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="context-box">
|
||||
<div class="context-box-inner">
|
||||
<strong>问题:</strong>用户难以感知卡片内存在两类不同质检工单,且需要点击切换。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="index-cta">
|
||||
<a class="primary" href="independent-pills.html">独立胶囊 Tab(最新)→</a>
|
||||
<a class="secondary" href="compare-all-v2.html">第二组 · 强对比方案</a>
|
||||
<a class="secondary" href="compare-all.html">第一组 · 渐进改良方案</a>
|
||||
</div>
|
||||
|
||||
<div class="batch-section">
|
||||
<h2>独立胶囊 Tab(现网结构 + 分离间距)</h2>
|
||||
<p>去掉轨道连体容器,每个 Tab 独立白底胶囊,间距 16 / 24 / 32px 三档对比。</p>
|
||||
</div>
|
||||
<div class="index-grid">
|
||||
<div class="index-card">
|
||||
<h3>A · 轨道内连体</h3>
|
||||
<p>现网对照:<code>panel-pill-tabs__track</code> 绿底容器。</p>
|
||||
<span class="tag">对照</span>
|
||||
</div>
|
||||
<div class="index-card">
|
||||
<h3>B · 独立胶囊 16px</h3>
|
||||
<p>独立边框 + 来源色,间距 16px。</p>
|
||||
<span class="tag tag--rec">推荐</span>
|
||||
<span class="tag tag--new">最新</span>
|
||||
</div>
|
||||
<div class="index-card">
|
||||
<h3>C · 独立胶囊 24px</h3>
|
||||
<p>分离感更强。</p>
|
||||
<span class="tag tag--new">最新</span>
|
||||
</div>
|
||||
<div class="index-card">
|
||||
<h3>D · 独立胶囊 32px 放大</h3>
|
||||
<p>最大间距 + 略放大点击区域。</p>
|
||||
<span class="tag tag--new">最新</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="batch-section">
|
||||
<h2>第二组 · 强对比(推荐先看)</h2>
|
||||
<p>加大色块面积、两条工单始终可见、未选中显式「切换/点击」 affordance。</p>
|
||||
</div>
|
||||
<div class="index-grid">
|
||||
<div class="index-card">
|
||||
<h3>N1 · 双色分栏顶栏</h3>
|
||||
<p>整宽 50/50 绿/琥珀分栏,未选中降饱和 + 👆 动画提示。</p>
|
||||
<span class="tag tag--rec">推荐</span>
|
||||
<span class="tag tag--new">第二组</span>
|
||||
</div>
|
||||
<div class="index-card">
|
||||
<h3>N2 · 双行 Radio 清单</h3>
|
||||
<p>列表单选形态,未选中行「切换至此」按钮。</p>
|
||||
<span class="tag tag--new">第二组</span>
|
||||
</div>
|
||||
<div class="index-card">
|
||||
<h3>N3 · 大开关 Toggle</h3>
|
||||
<p>居中 oversized 二选一开关,emoji + 粗体类别名。</p>
|
||||
<span class="tag tag--rec">推荐</span>
|
||||
<span class="tag tag--new">第二组</span>
|
||||
</div>
|
||||
<div class="index-card">
|
||||
<h3>N4 · 图标宫格</h3>
|
||||
<p>56px 大图标 + 虚线边框 = 可点击,视觉重量最大。</p>
|
||||
<span class="tag tag--new">第二组</span>
|
||||
</div>
|
||||
<div class="index-card">
|
||||
<h3>N5 · 双摘要条</h3>
|
||||
<p>提示横幅 + 并排 Chip,未选中绿色「切换」按钮。</p>
|
||||
<span class="tag tag--new">第二组</span>
|
||||
</div>
|
||||
<div class="index-card">
|
||||
<h3>N6 · 左导航 + 右预览</h3>
|
||||
<p>Master-Detail,左侧工单列表始终可见。</p>
|
||||
<span class="tag tag--new">第二组</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="batch-section">
|
||||
<h2>第一组 · 渐进改良</h2>
|
||||
<p>在现有 pill-tab 形态上微调,改动量较小。</p>
|
||||
</div>
|
||||
<div class="index-grid">
|
||||
<div class="index-card">
|
||||
<h3>V0–V5</h3>
|
||||
<p>胶囊 Tab、双卡片、步骤条、Segmented、色条 Tab 等 6 套。</p>
|
||||
<span class="tag">第一组</span>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_types_import_components_d_ts", "label": "components.d.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts", "source_location": "L1"}], "edges": [], "raw_calls": []}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_quality_inspection_qc_work_order_qcworkordersamplegroup_vue", "label": "QcWorkOrderSampleGroup.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-work-order/QcWorkOrderSampleGroup.vue", "source_location": "L1"}], "edges": [], "raw_calls": []}
|
||||
Reference in new issue
Block a user