1497 lines
44 KiB
HTML
1497 lines
44 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>入库放行 · 批量审核弹窗 Demo</title>
|
||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||
<link
|
||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
|
||
rel="stylesheet"
|
||
/>
|
||
<style>
|
||
:root {
|
||
--primary: #10b981;
|
||
--primary-dark: #059669;
|
||
--primary-bg: #ecfdf5;
|
||
--text: #1e293b;
|
||
--text-muted: #64748b;
|
||
--text-label: #334155;
|
||
--border: #d9e8e2;
|
||
--border-soft: #e2e8f0;
|
||
--bg-page: #f1f5f9;
|
||
--surface: #ffffff;
|
||
--table-head: #f8fafc;
|
||
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||
--radius: 10px;
|
||
--mask: rgba(15, 23, 42, 0.35);
|
||
--warn: #d97706;
|
||
--warn-bg: #fffbeb;
|
||
--danger: #dc2626;
|
||
--danger-bg: #fef2f2;
|
||
}
|
||
|
||
* {
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
html,
|
||
body {
|
||
margin: 0;
|
||
min-height: 100%;
|
||
}
|
||
|
||
body {
|
||
font-family: Inter, -apple-system, BlinkMacSystemFont, sans-serif;
|
||
font-size: 14px;
|
||
line-height: 1.5;
|
||
color: var(--text);
|
||
background: var(--bg-page);
|
||
}
|
||
|
||
button {
|
||
font-family: inherit;
|
||
}
|
||
|
||
.page {
|
||
min-height: 100vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.banner {
|
||
position: sticky;
|
||
top: 0;
|
||
z-index: 20;
|
||
background: var(--surface);
|
||
border-bottom: 1px solid var(--border-soft);
|
||
padding: 14px 24px 16px;
|
||
box-shadow: var(--shadow);
|
||
}
|
||
|
||
.banner h1 {
|
||
margin: 0;
|
||
font-size: 16px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.banner p {
|
||
margin: 6px 0 0;
|
||
font-size: 13px;
|
||
color: var(--text-muted);
|
||
max-width: 960px;
|
||
}
|
||
|
||
.banner p strong {
|
||
color: var(--primary-dark);
|
||
font-weight: 600;
|
||
}
|
||
|
||
.scheme-row {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
gap: 8px;
|
||
margin-top: 12px;
|
||
}
|
||
|
||
.scheme-row > span {
|
||
font-size: 12px;
|
||
color: var(--text-muted);
|
||
margin-right: 4px;
|
||
}
|
||
|
||
.scheme-btn {
|
||
height: 32px;
|
||
padding: 0 12px;
|
||
border-radius: 8px;
|
||
border: 1px solid var(--border);
|
||
background: var(--surface);
|
||
color: var(--text);
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.scheme-btn:hover {
|
||
background: #f8fafc;
|
||
}
|
||
|
||
.scheme-btn.is-active {
|
||
background: var(--primary);
|
||
border-color: var(--primary);
|
||
color: #fff;
|
||
}
|
||
|
||
.scheme-btn.is-rec::after {
|
||
content: '推荐';
|
||
margin-left: 6px;
|
||
font-size: 10px;
|
||
font-weight: 700;
|
||
padding: 1px 5px;
|
||
border-radius: 4px;
|
||
background: rgba(255, 255, 255, 0.22);
|
||
}
|
||
|
||
.scheme-btn:not(.is-active).is-rec::after {
|
||
background: var(--primary-bg);
|
||
color: var(--primary-dark);
|
||
}
|
||
|
||
.note {
|
||
margin-top: 10px;
|
||
font-size: 12px;
|
||
color: var(--text-muted);
|
||
padding: 8px 10px;
|
||
background: #f8fafc;
|
||
border: 1px solid var(--border-soft);
|
||
border-radius: 8px;
|
||
max-width: 960px;
|
||
}
|
||
|
||
.stage {
|
||
flex: 1;
|
||
position: relative;
|
||
min-height: 0;
|
||
}
|
||
|
||
.backdrop {
|
||
position: absolute;
|
||
inset: 0;
|
||
background: var(--mask);
|
||
display: flex;
|
||
align-items: flex-start;
|
||
justify-content: center;
|
||
padding: 16px 16px 24px;
|
||
overflow: auto;
|
||
}
|
||
|
||
.dialog {
|
||
display: none;
|
||
flex-direction: column;
|
||
background: var(--surface);
|
||
border-radius: var(--radius);
|
||
box-shadow: 0 16px 48px rgba(15, 23, 42, 0.18);
|
||
max-height: calc(100vh - 140px);
|
||
overflow: hidden;
|
||
width: min(1280px, 100%);
|
||
}
|
||
|
||
.dialog.is-show {
|
||
display: flex;
|
||
}
|
||
|
||
.dialog--unified {
|
||
width: min(640px, 100%);
|
||
}
|
||
|
||
.dialog--table {
|
||
width: min(980px, 100%);
|
||
}
|
||
|
||
.dialog-head {
|
||
flex-shrink: 0;
|
||
padding: 16px 22px 14px;
|
||
border-bottom: 1px solid var(--border-soft);
|
||
}
|
||
|
||
.dialog-head__row {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
justify-content: space-between;
|
||
gap: 12px;
|
||
}
|
||
|
||
.dialog-head h2 {
|
||
margin: 0;
|
||
font-size: 16px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.dialog-head .sub {
|
||
margin: 4px 0 0;
|
||
font-size: 12px;
|
||
color: var(--text-muted);
|
||
}
|
||
|
||
.icon-btn {
|
||
width: 28px;
|
||
height: 28px;
|
||
border: none;
|
||
background: transparent;
|
||
color: var(--text-muted);
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.icon-btn:hover {
|
||
background: #f1f5f9;
|
||
color: var(--text);
|
||
}
|
||
|
||
.mode-tabs {
|
||
display: inline-flex;
|
||
gap: 4px;
|
||
margin-top: 12px;
|
||
padding: 3px;
|
||
background: #f1f5f9;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.mode-tab {
|
||
height: 28px;
|
||
padding: 0 12px;
|
||
border: none;
|
||
border-radius: 6px;
|
||
background: transparent;
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
color: var(--text-muted);
|
||
cursor: pointer;
|
||
}
|
||
|
||
.mode-tab.is-active {
|
||
background: #fff;
|
||
color: var(--primary-dark);
|
||
box-shadow: var(--shadow);
|
||
}
|
||
|
||
.dialog-body {
|
||
flex: 1;
|
||
min-height: 0;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* —— Scheme A: 队列逐条 —— */
|
||
.queue-layout {
|
||
display: grid;
|
||
grid-template-columns: 240px minmax(0, 1.55fr) minmax(300px, 0.9fr);
|
||
height: 100%;
|
||
min-height: 520px;
|
||
}
|
||
|
||
.queue-pane {
|
||
border-right: 1px solid var(--border-soft);
|
||
background: #fcfdfd;
|
||
display: flex;
|
||
flex-direction: column;
|
||
min-height: 0;
|
||
}
|
||
|
||
.queue-pane__h {
|
||
flex-shrink: 0;
|
||
padding: 12px 14px;
|
||
border-bottom: 1px solid var(--border-soft);
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
letter-spacing: 0.04em;
|
||
color: var(--text-muted);
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.queue-pane__h em {
|
||
font-style: normal;
|
||
color: var(--primary-dark);
|
||
font-weight: 700;
|
||
}
|
||
|
||
.queue-list {
|
||
flex: 1;
|
||
overflow: auto;
|
||
padding: 8px;
|
||
}
|
||
|
||
.queue-item {
|
||
width: 100%;
|
||
text-align: left;
|
||
border: 1px solid transparent;
|
||
background: transparent;
|
||
border-radius: 8px;
|
||
padding: 10px 10px;
|
||
cursor: pointer;
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
.queue-item:hover {
|
||
background: #f8fafc;
|
||
}
|
||
|
||
.queue-item.is-active {
|
||
background: var(--primary-bg);
|
||
border-color: #a7f3d0;
|
||
}
|
||
|
||
.queue-item.is-done {
|
||
opacity: 0.72;
|
||
}
|
||
|
||
.queue-item__code {
|
||
font-size: 13px;
|
||
font-weight: 700;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
|
||
.queue-item__meta {
|
||
margin-top: 2px;
|
||
font-size: 11px;
|
||
color: var(--text-muted);
|
||
display: flex;
|
||
justify-content: space-between;
|
||
gap: 8px;
|
||
}
|
||
|
||
.status-dot {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.status-dot::before {
|
||
content: '';
|
||
width: 6px;
|
||
height: 6px;
|
||
border-radius: 50%;
|
||
background: #94a3b8;
|
||
}
|
||
|
||
.status-dot--pending::before {
|
||
background: var(--warn);
|
||
}
|
||
|
||
.status-dot--ok::before {
|
||
background: var(--primary);
|
||
}
|
||
|
||
.status-dot--bad::before {
|
||
background: var(--danger);
|
||
}
|
||
|
||
.evidence-pane {
|
||
min-width: 0;
|
||
overflow: auto;
|
||
padding: 14px 16px 18px;
|
||
border-right: 1px solid var(--border-soft);
|
||
background: #fcfdfd;
|
||
}
|
||
|
||
.form-pane {
|
||
min-width: 0;
|
||
overflow: auto;
|
||
padding: 14px 18px 18px;
|
||
background: var(--surface);
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
.hero {
|
||
padding: 10px 12px;
|
||
background: var(--table-head);
|
||
border: 1px solid var(--border-soft);
|
||
border-radius: 8px;
|
||
margin-bottom: 12px;
|
||
}
|
||
|
||
.hero__grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 6px 16px;
|
||
}
|
||
|
||
.meta-row {
|
||
display: flex;
|
||
gap: 8px;
|
||
font-size: 13px;
|
||
min-width: 0;
|
||
}
|
||
|
||
.meta-row .k {
|
||
color: var(--text-label);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.meta-row .v {
|
||
font-weight: 600;
|
||
overflow-wrap: anywhere;
|
||
}
|
||
|
||
.verdict {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
margin-top: 8px;
|
||
}
|
||
|
||
.chip {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
height: 22px;
|
||
padding: 0 8px;
|
||
border-radius: 6px;
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
background: #f1f5f9;
|
||
color: var(--text-muted);
|
||
}
|
||
|
||
.chip--ok {
|
||
background: var(--primary-bg);
|
||
color: #047857;
|
||
}
|
||
|
||
.chip--warn {
|
||
background: var(--warn-bg);
|
||
color: var(--warn);
|
||
}
|
||
|
||
.block {
|
||
border: 1px solid var(--border-soft);
|
||
border-radius: 8px;
|
||
background: #fff;
|
||
margin-bottom: 8px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.block > summary {
|
||
list-style: none;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 9px 12px;
|
||
font-size: 13px;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.block > summary::-webkit-details-marker {
|
||
display: none;
|
||
}
|
||
|
||
.block-body {
|
||
padding: 0 12px 12px;
|
||
border-top: 1px solid #f1f5f9;
|
||
}
|
||
|
||
.kv-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 8px 16px;
|
||
padding-top: 10px;
|
||
}
|
||
|
||
.kv dt {
|
||
margin: 0;
|
||
font-size: 12px;
|
||
color: var(--text-label);
|
||
}
|
||
|
||
.kv dd {
|
||
margin: 2px 0 0;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.tag {
|
||
display: inline-flex;
|
||
height: 20px;
|
||
padding: 0 7px;
|
||
border-radius: 4px;
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
align-items: center;
|
||
}
|
||
|
||
.tag--success {
|
||
background: var(--primary-bg);
|
||
color: #047857;
|
||
}
|
||
|
||
.tag--info {
|
||
background: #f1f5f9;
|
||
color: var(--text-muted);
|
||
}
|
||
|
||
.pane-title {
|
||
margin: 0 0 10px;
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
letter-spacing: 0.04em;
|
||
color: var(--text-muted);
|
||
}
|
||
|
||
.progress-bar {
|
||
margin-bottom: 12px;
|
||
padding: 8px 10px;
|
||
background: var(--primary-bg);
|
||
border: 1px solid #a7f3d0;
|
||
border-radius: 8px;
|
||
font-size: 12px;
|
||
color: #047857;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.field {
|
||
margin-bottom: 14px;
|
||
}
|
||
|
||
.field label {
|
||
display: block;
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.radios {
|
||
display: flex;
|
||
gap: 16px;
|
||
height: 36px;
|
||
align-items: center;
|
||
}
|
||
|
||
.radios label {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
margin: 0;
|
||
cursor: pointer;
|
||
font-weight: 400;
|
||
}
|
||
|
||
textarea {
|
||
width: 100%;
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
padding: 8px 10px;
|
||
font: inherit;
|
||
font-size: 13px;
|
||
resize: vertical;
|
||
min-height: 72px;
|
||
}
|
||
|
||
textarea:focus {
|
||
outline: none;
|
||
border-color: var(--primary);
|
||
box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.15);
|
||
}
|
||
|
||
.upload-row {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
}
|
||
|
||
.upload-card {
|
||
width: 140px;
|
||
height: 96px;
|
||
border: 1px dashed #a7f3d0;
|
||
border-radius: 8px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 6px;
|
||
color: #047857;
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
background: #f8fffb;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.apply-box {
|
||
margin-top: auto;
|
||
padding: 10px 12px;
|
||
background: #f8fafc;
|
||
border: 1px solid var(--border-soft);
|
||
border-radius: 8px;
|
||
font-size: 12px;
|
||
color: var(--text-label);
|
||
}
|
||
|
||
.apply-box label {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 8px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.apply-box input {
|
||
margin-top: 2px;
|
||
accent-color: var(--primary);
|
||
}
|
||
|
||
.apply-box .hint {
|
||
margin-top: 4px;
|
||
color: var(--text-muted);
|
||
font-size: 11px;
|
||
padding-left: 22px;
|
||
}
|
||
|
||
.dialog-foot {
|
||
flex-shrink: 0;
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
gap: 8px;
|
||
padding: 12px 18px;
|
||
border-top: 1px solid var(--border-soft);
|
||
background: #fff;
|
||
}
|
||
|
||
.dialog-foot .spacer {
|
||
margin-right: auto;
|
||
font-size: 12px;
|
||
color: var(--text-muted);
|
||
}
|
||
|
||
.btn {
|
||
height: 36px;
|
||
padding: 0 14px;
|
||
border-radius: 8px;
|
||
border: 1px solid var(--border);
|
||
background: #fff;
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
}
|
||
|
||
.btn:hover {
|
||
background: #f8fafc;
|
||
}
|
||
|
||
.btn--primary {
|
||
background: var(--primary);
|
||
border-color: var(--primary);
|
||
color: #fff;
|
||
}
|
||
|
||
.btn--primary:hover {
|
||
background: var(--primary-dark);
|
||
}
|
||
|
||
.btn--ghost-danger {
|
||
color: var(--danger);
|
||
border-color: #fecaca;
|
||
}
|
||
|
||
.btn--ghost-danger:hover {
|
||
background: var(--danger-bg);
|
||
}
|
||
|
||
/* —— Scheme B: 统一结论(现状增强) —— */
|
||
.unified-body {
|
||
padding: 18px 22px;
|
||
overflow: auto;
|
||
}
|
||
|
||
.target-hint {
|
||
margin: 0 0 14px;
|
||
padding: 10px 12px;
|
||
background: var(--warn-bg);
|
||
border: 1px solid #fde68a;
|
||
border-radius: 8px;
|
||
font-size: 13px;
|
||
color: #92400e;
|
||
}
|
||
|
||
.target-hint strong {
|
||
font-weight: 700;
|
||
}
|
||
|
||
.mini-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: 12px;
|
||
margin-bottom: 16px;
|
||
}
|
||
|
||
.mini-table th,
|
||
.mini-table td {
|
||
padding: 8px 10px;
|
||
border-bottom: 1px solid var(--border-soft);
|
||
text-align: left;
|
||
}
|
||
|
||
.mini-table th {
|
||
background: var(--table-head);
|
||
font-weight: 600;
|
||
color: var(--text-label);
|
||
}
|
||
|
||
.mini-table tr:last-child td {
|
||
border-bottom: none;
|
||
}
|
||
|
||
/* —— Scheme C: 表格 + 行内 —— */
|
||
.table-body {
|
||
padding: 0;
|
||
overflow: auto;
|
||
max-height: calc(100vh - 280px);
|
||
}
|
||
|
||
.batch-bar {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: center;
|
||
gap: 10px 16px;
|
||
padding: 12px 18px;
|
||
border-bottom: 1px solid var(--border-soft);
|
||
background: #f8fffb;
|
||
}
|
||
|
||
.batch-bar .label {
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
color: var(--text-muted);
|
||
}
|
||
|
||
.data-table {
|
||
width: 100%;
|
||
border-collapse: collapse;
|
||
font-size: 13px;
|
||
}
|
||
|
||
.data-table th,
|
||
.data-table td {
|
||
padding: 10px 12px;
|
||
border-bottom: 1px solid var(--border-soft);
|
||
text-align: left;
|
||
vertical-align: middle;
|
||
}
|
||
|
||
.data-table th {
|
||
position: sticky;
|
||
top: 0;
|
||
background: var(--table-head);
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
color: var(--text-label);
|
||
z-index: 1;
|
||
}
|
||
|
||
.data-table .mono {
|
||
font-variant-numeric: tabular-nums;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.row-actions {
|
||
display: flex;
|
||
gap: 6px;
|
||
}
|
||
|
||
.link-btn {
|
||
border: none;
|
||
background: none;
|
||
color: var(--primary-dark);
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
padding: 0;
|
||
}
|
||
|
||
.link-btn:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.expand-panel {
|
||
display: none;
|
||
background: #fcfdfd;
|
||
}
|
||
|
||
.expand-panel.is-open {
|
||
display: table-row;
|
||
}
|
||
|
||
.expand-panel td {
|
||
padding: 0 12px 14px 36px;
|
||
}
|
||
|
||
.expand-inner {
|
||
display: grid;
|
||
grid-template-columns: 1fr 280px;
|
||
gap: 12px;
|
||
padding: 12px;
|
||
border: 1px solid var(--border-soft);
|
||
border-radius: 8px;
|
||
background: #fff;
|
||
}
|
||
|
||
.toast {
|
||
position: fixed;
|
||
bottom: 24px;
|
||
left: 50%;
|
||
transform: translateX(-50%) translateY(20px);
|
||
background: #1e293b;
|
||
color: #fff;
|
||
padding: 10px 16px;
|
||
border-radius: 8px;
|
||
font-size: 13px;
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition:
|
||
opacity 0.2s,
|
||
transform 0.2s;
|
||
z-index: 50;
|
||
}
|
||
|
||
.toast.is-show {
|
||
opacity: 1;
|
||
transform: translateX(-50%) translateY(0);
|
||
}
|
||
|
||
@media (max-width: 1100px) {
|
||
.queue-layout {
|
||
grid-template-columns: 200px minmax(0, 1fr);
|
||
}
|
||
|
||
.form-pane {
|
||
grid-column: 1 / -1;
|
||
border-top: 1px solid var(--border-soft);
|
||
max-height: 320px;
|
||
}
|
||
|
||
.expand-inner {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="page">
|
||
<header class="banner">
|
||
<h1>入库放行审核 · 批量审核弹窗 Demo</h1>
|
||
<p>
|
||
列表勾选多条后点「批量审核」。目标:既可<strong>逐条核对证据后审核</strong>,也可<strong>对剩余项套用同一结论快速批量提交</strong>。
|
||
下方可切换三种方案对比(Fresh Mint)。
|
||
</p>
|
||
<div class="scheme-row">
|
||
<span>方案</span>
|
||
<button type="button" class="scheme-btn is-rec is-active" data-scheme="queue">
|
||
A · 队列逐条 + 套用剩余
|
||
</button>
|
||
<button type="button" class="scheme-btn" data-scheme="unified">
|
||
B · 统一结论(现状)
|
||
</button>
|
||
<button type="button" class="scheme-btn" data-scheme="table">
|
||
C · 表格行内审核
|
||
</button>
|
||
</div>
|
||
<div class="note" id="schemeNote">
|
||
<strong>A 推荐:</strong>左侧待审队列 → 中间复用单条审核的证据区 →
|
||
右侧结论表单。默认「提交本条并下一条」;勾选「将结论套用到剩余未审项」即可一键批量。与现有单条审核体验连续。
|
||
</div>
|
||
</header>
|
||
|
||
<div class="stage">
|
||
<div class="backdrop">
|
||
<!-- ========== Scheme A ========== -->
|
||
<div class="dialog is-show" id="dlg-queue" role="dialog" aria-label="批量审核-队列">
|
||
<div class="dialog-head">
|
||
<div class="dialog-head__row">
|
||
<div>
|
||
<h2>批量审核(5 条)</h2>
|
||
<p class="sub">逐条核对接收 / 质检 / 生产证据后给出结论;也可对剩余项统一套用。</p>
|
||
</div>
|
||
<button type="button" class="icon-btn" aria-label="关闭" title="关闭">✕</button>
|
||
</div>
|
||
<div class="mode-tabs" role="tablist">
|
||
<button type="button" class="mode-tab is-active" data-mode="per">逐条核对</button>
|
||
<button type="button" class="mode-tab" data-mode="batch">统一提交</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dialog-body" id="queue-per-body">
|
||
<div class="queue-layout">
|
||
<aside class="queue-pane">
|
||
<div class="queue-pane__h">
|
||
<span>待审队列</span>
|
||
<em id="queueProgress">1 / 5</em>
|
||
</div>
|
||
<div class="queue-list" id="queueList"></div>
|
||
</aside>
|
||
|
||
<section class="evidence-pane">
|
||
<div class="hero">
|
||
<div class="hero__grid">
|
||
<div class="meta-row">
|
||
<span class="k">实验室入库编码</span>
|
||
<span class="v" id="evLab">RK-2026-0819-003</span>
|
||
</div>
|
||
<div class="meta-row">
|
||
<span class="k">样本编码</span>
|
||
<span class="v" id="evCode">YP-CS-20260819-001</span>
|
||
</div>
|
||
</div>
|
||
<div class="verdict">
|
||
<span class="chip chip--ok">样本接收:接收</span>
|
||
<span class="chip chip--ok">质检工单:已完成</span>
|
||
<span class="chip chip--ok">生产工单:已完成</span>
|
||
</div>
|
||
</div>
|
||
|
||
<details class="block" open>
|
||
<summary><span>接收信息</span><span>▾</span></summary>
|
||
<div class="block-body">
|
||
<dl class="kv-grid">
|
||
<div class="kv">
|
||
<dt>接收人</dt>
|
||
<dd>张三</dd>
|
||
</div>
|
||
<div class="kv">
|
||
<dt>接收时间</dt>
|
||
<dd>2026-08-18 14:22</dd>
|
||
</div>
|
||
<div class="kv">
|
||
<dt>样本类型</dt>
|
||
<dd>脐带血</dd>
|
||
</div>
|
||
<div class="kv">
|
||
<dt>接收结论</dt>
|
||
<dd><span class="tag tag--success">接收</span></dd>
|
||
</div>
|
||
</dl>
|
||
</div>
|
||
</details>
|
||
|
||
<details class="block" open>
|
||
<summary><span>质检信息</span><span>▾</span></summary>
|
||
<div class="block-body">
|
||
<dl class="kv-grid">
|
||
<div class="kv">
|
||
<dt>工单状态</dt>
|
||
<dd><span class="tag tag--success">已完成</span></dd>
|
||
</div>
|
||
<div class="kv">
|
||
<dt>门禁结论</dt>
|
||
<dd><span class="tag tag--success">通过</span></dd>
|
||
</div>
|
||
<div class="kv">
|
||
<dt>过程质检</dt>
|
||
<dd>2 项已完成</dd>
|
||
</div>
|
||
<div class="kv">
|
||
<dt>异常项</dt>
|
||
<dd>无</dd>
|
||
</div>
|
||
</dl>
|
||
</div>
|
||
</details>
|
||
|
||
<details class="block" open>
|
||
<summary><span>生产信息</span><span>▾</span></summary>
|
||
<div class="block-body">
|
||
<dl class="kv-grid">
|
||
<div class="kv">
|
||
<dt>工单状态</dt>
|
||
<dd><span class="tag tag--success">已完成</span></dd>
|
||
</div>
|
||
<div class="kv">
|
||
<dt>产出数量</dt>
|
||
<dd>2 袋</dd>
|
||
</div>
|
||
<div class="kv">
|
||
<dt>废料</dt>
|
||
<dd>0</dd>
|
||
</div>
|
||
<div class="kv">
|
||
<dt>执行人</dt>
|
||
<dd>李四</dd>
|
||
</div>
|
||
</dl>
|
||
</div>
|
||
</details>
|
||
</section>
|
||
|
||
<section class="form-pane">
|
||
<p class="pane-title">本条审核</p>
|
||
<div class="progress-bar" id="formProgress">正在审核第 1 条 · 还剩 4 条未审</div>
|
||
|
||
<div class="field">
|
||
<label>审核结论</label>
|
||
<div class="radios">
|
||
<label><input type="radio" name="q-conc" value="tg" checked /> 通过</label>
|
||
<label><input type="radio" name="q-conc" value="btg" /> 不通过</label>
|
||
</div>
|
||
</div>
|
||
<div class="field">
|
||
<label>备注</label>
|
||
<textarea placeholder="可选" maxlength="1000"></textarea>
|
||
</div>
|
||
<div class="field">
|
||
<label>附件</label>
|
||
<div class="upload-row">
|
||
<div class="upload-card">
|
||
<span style="font-size: 20px">+</span>
|
||
<span>上传附件</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="apply-box">
|
||
<label>
|
||
<input type="checkbox" id="applyRest" />
|
||
<span
|
||
>将当前结论 / 备注 / 附件<strong>套用到剩余未审项</strong>并一次性提交</span
|
||
>
|
||
</label>
|
||
<div class="hint">
|
||
勾选后底栏主按钮变为「批量提交剩余」;适合证据已预览、结论一致的场景。
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dialog-body" id="queue-batch-body" style="display: none">
|
||
<div class="unified-body">
|
||
<p class="target-hint">
|
||
将对已选 <strong>5</strong> 条记录提交<strong>相同</strong>审核结果(不逐条展示证据)。
|
||
</p>
|
||
<table class="mini-table">
|
||
<thead>
|
||
<tr>
|
||
<th>样本编码</th>
|
||
<th>入库编码</th>
|
||
<th>样本名称</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="unifiedMiniTbody"></tbody>
|
||
</table>
|
||
<div class="field">
|
||
<label>审核结论</label>
|
||
<div class="radios">
|
||
<label><input type="radio" name="qb-conc" value="tg" checked /> 通过</label>
|
||
<label><input type="radio" name="qb-conc" value="btg" /> 不通过</label>
|
||
</div>
|
||
</div>
|
||
<div class="field">
|
||
<label>备注</label>
|
||
<textarea placeholder="可选,将写入全部已选记录"></textarea>
|
||
</div>
|
||
<div class="field">
|
||
<label>附件</label>
|
||
<div class="upload-row">
|
||
<div class="upload-card">
|
||
<span style="font-size: 20px">+</span>
|
||
<span>上传附件</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dialog-foot" id="queueFoot">
|
||
<span class="spacer" id="queueFootHint">建议:有疑义的样本逐条看证据;同质样本可套用剩余。</span>
|
||
<button type="button" class="btn">取消</button>
|
||
<button type="button" class="btn btn--ghost-danger" id="btnSkip">跳过本条</button>
|
||
<button type="button" class="btn btn--primary" id="btnQueuePrimary">
|
||
✓ 提交本条并下一条
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ========== Scheme B ========== -->
|
||
<div class="dialog dialog--unified" id="dlg-unified" role="dialog" aria-label="批量审核-统一">
|
||
<div class="dialog-head">
|
||
<div class="dialog-head__row">
|
||
<div>
|
||
<h2>批量审核(5 条)</h2>
|
||
<p class="sub">与当前线上一致:一份结论写入全部已选记录。</p>
|
||
</div>
|
||
<button type="button" class="icon-btn" aria-label="关闭">✕</button>
|
||
</div>
|
||
</div>
|
||
<div class="dialog-body" style="overflow: auto">
|
||
<div class="unified-body">
|
||
<p class="target-hint">
|
||
将对已选 <strong>5</strong> 条记录提交相同审核结果。
|
||
</p>
|
||
<table class="mini-table">
|
||
<thead>
|
||
<tr>
|
||
<th>#</th>
|
||
<th>样本编码</th>
|
||
<th>入库编码</th>
|
||
<th>名称</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="schemeBTbody"></tbody>
|
||
</table>
|
||
<div class="field">
|
||
<label>审核结论</label>
|
||
<div class="radios">
|
||
<label><input type="radio" name="b-conc" value="tg" checked /> 通过</label>
|
||
<label><input type="radio" name="b-conc" value="btg" /> 不通过</label>
|
||
</div>
|
||
</div>
|
||
<div class="field">
|
||
<label>备注</label>
|
||
<textarea placeholder="可选"></textarea>
|
||
</div>
|
||
<div class="field">
|
||
<label>附件</label>
|
||
<div class="upload-row">
|
||
<div class="upload-card">
|
||
<span style="font-size: 20px">+</span>
|
||
<span>上传附件</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="dialog-foot">
|
||
<button type="button" class="btn">取消</button>
|
||
<button type="button" class="btn btn--primary" data-toast="已批量提交 5 条(Demo)">
|
||
✓ 确定
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ========== Scheme C ========== -->
|
||
<div class="dialog dialog--table" id="dlg-table" role="dialog" aria-label="批量审核-表格">
|
||
<div class="dialog-head">
|
||
<div class="dialog-head__row">
|
||
<div>
|
||
<h2>批量审核(5 条)</h2>
|
||
<p class="sub">表格内逐行结论;顶栏可对勾选行统一填结论后批量提交。</p>
|
||
</div>
|
||
<button type="button" class="icon-btn" aria-label="关闭">✕</button>
|
||
</div>
|
||
</div>
|
||
<div class="dialog-body table-body">
|
||
<div class="batch-bar">
|
||
<span class="label">批量填入</span>
|
||
<div class="radios" style="height: auto">
|
||
<label><input type="radio" name="c-bulk" value="tg" checked /> 通过</label>
|
||
<label><input type="radio" name="c-bulk" value="btg" /> 不通过</label>
|
||
</div>
|
||
<button type="button" class="btn" id="btnFillRows" style="height: 32px">
|
||
填入已勾选行
|
||
</button>
|
||
<span style="font-size: 12px; color: var(--text-muted)"
|
||
>也可点「展开」看证据后单独改结论</span
|
||
>
|
||
</div>
|
||
<table class="data-table">
|
||
<thead>
|
||
<tr>
|
||
<th style="width: 40px"><input type="checkbox" id="checkAll" checked /></th>
|
||
<th>样本编码</th>
|
||
<th>入库编码</th>
|
||
<th>质检</th>
|
||
<th>生产</th>
|
||
<th>结论</th>
|
||
<th style="width: 100px">操作</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="schemeCTbody"></tbody>
|
||
</table>
|
||
</div>
|
||
<div class="dialog-foot">
|
||
<span class="spacer">未填结论的行提交时将提示补全</span>
|
||
<button type="button" class="btn">取消</button>
|
||
<button type="button" class="btn btn--primary" data-toast="已按行结论提交(Demo)">
|
||
✓ 提交全部
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="toast" id="toast"></div>
|
||
|
||
<script>
|
||
const SAMPLES = [
|
||
{
|
||
id: '1',
|
||
code: 'YP-CS-20260819-001',
|
||
lab: 'RK-2026-0819-003',
|
||
name: '脐带血样本 A',
|
||
qc: '已完成',
|
||
prod: '已完成'
|
||
},
|
||
{
|
||
id: '2',
|
||
code: 'YP-CS-20260819-002',
|
||
lab: 'RK-2026-0819-004',
|
||
name: '脐带血样本 B',
|
||
qc: '已完成',
|
||
prod: '已完成'
|
||
},
|
||
{
|
||
id: '3',
|
||
code: 'YP-CS-20260818-015',
|
||
lab: 'RK-2026-0818-021',
|
||
name: '胎盘组织 C',
|
||
qc: '已完成',
|
||
prod: '已完成'
|
||
},
|
||
{
|
||
id: '4',
|
||
code: 'YP-RD-20260817-008',
|
||
lab: 'RK-2026-0817-011',
|
||
name: '捐赠样本 D',
|
||
qc: '已完成',
|
||
prod: '已完成'
|
||
},
|
||
{
|
||
id: '5',
|
||
code: 'YP-CS-20260816-022',
|
||
lab: 'RK-2026-0816-030',
|
||
name: '脐带血样本 E',
|
||
qc: '已完成',
|
||
prod: '已完成'
|
||
}
|
||
]
|
||
|
||
const notes = {
|
||
queue:
|
||
'<strong>A 推荐:</strong>左侧待审队列 → 中间复用单条审核的证据区 → 右侧结论表单。默认「提交本条并下一条」;勾选「将结论套用到剩余未审项」即可一键批量。与现有单条审核体验连续。',
|
||
unified:
|
||
'<strong>B 现状:</strong>窄弹窗 + 统一结论。效率最高,但看不到各样本证据,误审风险大;适合「已在列表/查看里确认过、结论必然一致」的场景。建议在清单上增加已选摘要表(本 Demo 已补)。',
|
||
table:
|
||
'<strong>C 表格行内:</strong>一屏看到全部已选;顶栏批量填结论,行内可展开证据。适合条数不多(≤10)且需要「大部分相同、个别例外」的微调。证据区复用成本较高。'
|
||
}
|
||
|
||
let activeIdx = 0
|
||
const decisions = SAMPLES.map(() => null) // null | 'tg' | 'btg'
|
||
|
||
function toast(msg) {
|
||
const el = document.getElementById('toast')
|
||
el.textContent = msg
|
||
el.classList.add('is-show')
|
||
clearTimeout(toast._t)
|
||
toast._t = setTimeout(() => el.classList.remove('is-show'), 2200)
|
||
}
|
||
|
||
function doneCount() {
|
||
return decisions.filter(Boolean).length
|
||
}
|
||
|
||
function renderQueue() {
|
||
const list = document.getElementById('queueList')
|
||
list.innerHTML = SAMPLES.map((s, i) => {
|
||
const d = decisions[i]
|
||
const st =
|
||
d === 'tg'
|
||
? 'status-dot--ok">已通过'
|
||
: d === 'btg'
|
||
? 'status-dot--bad">不通过'
|
||
: 'status-dot--pending">待审'
|
||
return `<button type="button" class="queue-item ${i === activeIdx ? 'is-active' : ''} ${d ? 'is-done' : ''}" data-idx="${i}">
|
||
<div class="queue-item__code">${s.code}</div>
|
||
<div class="queue-item__meta">
|
||
<span>${s.lab}</span>
|
||
<span class="status-dot ${st}</span>
|
||
</div>
|
||
</button>`
|
||
}).join('')
|
||
|
||
document.getElementById('queueProgress').textContent = `${activeIdx + 1} / ${SAMPLES.length}`
|
||
const left = SAMPLES.length - doneCount()
|
||
document.getElementById('formProgress').textContent =
|
||
`正在审核第 ${activeIdx + 1} 条 · 还剩 ${Math.max(left - (decisions[activeIdx] ? 0 : 1), 0)} 条未审(已完成 ${doneCount()})`
|
||
|
||
const s = SAMPLES[activeIdx]
|
||
document.getElementById('evLab').textContent = s.lab
|
||
document.getElementById('evCode').textContent = s.code
|
||
}
|
||
|
||
function fillMiniTables() {
|
||
const rows = SAMPLES.map(
|
||
(s, i) =>
|
||
`<tr><td>${s.code}</td><td>${s.lab}</td><td>${s.name}</td></tr>`
|
||
).join('')
|
||
document.getElementById('unifiedMiniTbody').innerHTML = rows
|
||
document.getElementById('schemeBTbody').innerHTML = SAMPLES.map(
|
||
(s, i) =>
|
||
`<tr><td>${i + 1}</td><td>${s.code}</td><td>${s.lab}</td><td>${s.name}</td></tr>`
|
||
).join('')
|
||
}
|
||
|
||
function renderSchemeC() {
|
||
const tb = document.getElementById('schemeCTbody')
|
||
tb.innerHTML = SAMPLES.map((s, i) => {
|
||
return `
|
||
<tr data-row="${i}">
|
||
<td><input type="checkbox" class="row-check" checked /></td>
|
||
<td class="mono">${s.code}</td>
|
||
<td>${s.lab}</td>
|
||
<td><span class="tag tag--success">${s.qc}</span></td>
|
||
<td><span class="tag tag--success">${s.prod}</span></td>
|
||
<td>
|
||
<select class="row-conc" style="height:32px;border:1px solid var(--border);border-radius:6px;padding:0 8px;font:inherit;font-size:12px">
|
||
<option value="">未填</option>
|
||
<option value="tg">通过</option>
|
||
<option value="btg">不通过</option>
|
||
</select>
|
||
</td>
|
||
<td class="row-actions">
|
||
<button type="button" class="link-btn expand-btn" data-idx="${i}">展开</button>
|
||
</td>
|
||
</tr>
|
||
<tr class="expand-panel" id="exp-${i}">
|
||
<td colspan="7">
|
||
<div class="expand-inner">
|
||
<div>
|
||
<div class="pane-title">证据摘要 · ${s.code}</div>
|
||
<div class="verdict" style="margin:0 0 8px">
|
||
<span class="chip chip--ok">接收:接收</span>
|
||
<span class="chip chip--ok">质检:${s.qc}</span>
|
||
<span class="chip chip--ok">生产:${s.prod}</span>
|
||
</div>
|
||
<p style="margin:0;font-size:12px;color:var(--text-muted)">此处可嵌入与单条审核相同的折叠证据块(接收 / 质检 / 生产)。Demo 仅示意布局。</p>
|
||
</div>
|
||
<div>
|
||
<div class="field" style="margin:0">
|
||
<label>行备注</label>
|
||
<textarea rows="3" placeholder="仅本条"></textarea>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</td>
|
||
</tr>`
|
||
}).join('')
|
||
}
|
||
|
||
function showScheme(name) {
|
||
document.querySelectorAll('.scheme-btn').forEach((b) => {
|
||
b.classList.toggle('is-active', b.dataset.scheme === name)
|
||
})
|
||
document.getElementById('schemeNote').innerHTML = notes[name]
|
||
document.getElementById('dlg-queue').classList.toggle('is-show', name === 'queue')
|
||
document.getElementById('dlg-unified').classList.toggle('is-show', name === 'unified')
|
||
document.getElementById('dlg-table').classList.toggle('is-show', name === 'table')
|
||
}
|
||
|
||
function updatePrimaryBtn() {
|
||
const apply = document.getElementById('applyRest').checked
|
||
const btn = document.getElementById('btnQueuePrimary')
|
||
const left = SAMPLES.length - doneCount()
|
||
if (apply) {
|
||
btn.textContent = `✓ 批量提交剩余(${left || SAMPLES.length})`
|
||
} else {
|
||
btn.textContent =
|
||
activeIdx >= SAMPLES.length - 1 && decisions.every(Boolean)
|
||
? '✓ 完成并关闭'
|
||
: '✓ 提交本条并下一条'
|
||
}
|
||
}
|
||
|
||
document.querySelectorAll('.scheme-btn').forEach((btn) => {
|
||
btn.addEventListener('click', () => showScheme(btn.dataset.scheme))
|
||
})
|
||
|
||
document.querySelectorAll('.mode-tab').forEach((tab) => {
|
||
tab.addEventListener('click', () => {
|
||
document.querySelectorAll('.mode-tab').forEach((t) => t.classList.remove('is-active'))
|
||
tab.classList.add('is-active')
|
||
const per = tab.dataset.mode === 'per'
|
||
document.getElementById('queue-per-body').style.display = per ? '' : 'none'
|
||
document.getElementById('queue-batch-body').style.display = per ? 'none' : ''
|
||
const foot = document.getElementById('queueFoot')
|
||
document.getElementById('btnSkip').style.display = per ? '' : 'none'
|
||
document.getElementById('queueFootHint').textContent = per
|
||
? '建议:有疑义的样本逐条看证据;同质样本可套用剩余。'
|
||
: '统一模式:一份结论写入全部 5 条,不等同于逐条核对。'
|
||
document.getElementById('btnQueuePrimary').textContent = per
|
||
? '✓ 提交本条并下一条'
|
||
: '✓ 统一提交 5 条'
|
||
if (!per) document.getElementById('applyRest').checked = false
|
||
})
|
||
})
|
||
|
||
document.getElementById('queueList').addEventListener('click', (e) => {
|
||
const item = e.target.closest('.queue-item')
|
||
if (!item) return
|
||
activeIdx = Number(item.dataset.idx)
|
||
renderQueue()
|
||
updatePrimaryBtn()
|
||
})
|
||
|
||
document.getElementById('applyRest').addEventListener('change', updatePrimaryBtn)
|
||
|
||
document.getElementById('btnSkip').addEventListener('click', () => {
|
||
if (activeIdx < SAMPLES.length - 1) {
|
||
activeIdx += 1
|
||
renderQueue()
|
||
updatePrimaryBtn()
|
||
toast('已跳过,进入下一条')
|
||
} else {
|
||
toast('已是最后一条')
|
||
}
|
||
})
|
||
|
||
document.getElementById('btnQueuePrimary').addEventListener('click', () => {
|
||
const modePer = document.querySelector('.mode-tab.is-active').dataset.mode === 'per'
|
||
if (!modePer) {
|
||
toast('已统一提交 5 条(Demo)')
|
||
return
|
||
}
|
||
const apply = document.getElementById('applyRest').checked
|
||
const conc = document.querySelector('input[name="q-conc"]:checked').value
|
||
if (apply) {
|
||
for (let i = 0; i < SAMPLES.length; i++) {
|
||
if (!decisions[i]) decisions[i] = conc
|
||
}
|
||
renderQueue()
|
||
updatePrimaryBtn()
|
||
toast(`已将结论套用并提交剩余项(Demo)`)
|
||
return
|
||
}
|
||
decisions[activeIdx] = conc
|
||
if (activeIdx < SAMPLES.length - 1) {
|
||
activeIdx += 1
|
||
toast(`第 ${activeIdx} 条已记录,继续下一条`)
|
||
} else {
|
||
toast('全部处理完毕(Demo)')
|
||
}
|
||
renderQueue()
|
||
updatePrimaryBtn()
|
||
})
|
||
|
||
document.getElementById('schemeCTbody').addEventListener('click', (e) => {
|
||
const btn = e.target.closest('.expand-btn')
|
||
if (!btn) return
|
||
const panel = document.getElementById('exp-' + btn.dataset.idx)
|
||
const open = panel.classList.toggle('is-open')
|
||
btn.textContent = open ? '收起' : '展开'
|
||
})
|
||
|
||
document.getElementById('btnFillRows').addEventListener('click', () => {
|
||
const v = document.querySelector('input[name="c-bulk"]:checked').value
|
||
document.querySelectorAll('#schemeCTbody tr[data-row]').forEach((tr) => {
|
||
const checked = tr.querySelector('.row-check').checked
|
||
if (checked) tr.querySelector('.row-conc').value = v
|
||
})
|
||
toast('已填入已勾选行(Demo)')
|
||
})
|
||
|
||
document.getElementById('checkAll').addEventListener('change', (e) => {
|
||
document.querySelectorAll('.row-check').forEach((c) => {
|
||
c.checked = e.target.checked
|
||
})
|
||
})
|
||
|
||
document.querySelectorAll('[data-toast]').forEach((btn) => {
|
||
btn.addEventListener('click', () => toast(btn.dataset.toast))
|
||
})
|
||
|
||
fillMiniTables()
|
||
renderQueue()
|
||
renderSchemeC()
|
||
updatePrimaryBtn()
|
||
</script>
|
||
</body>
|
||
</html>
|