发布 0.2.1 并完善工具边界与安全性

This commit is contained in:
mid
2026-08-10 14:49:43 +08:00
parent aca004c513
commit 32b7cc827c
47 changed files with 681 additions and 172 deletions
+26 -15
View File
@@ -79,6 +79,17 @@ button, input, select, textarea { font: inherit; letter-spacing: 0; }
button, a, input, select, textarea { outline-color: var(--accent); }
button { color: inherit; }
button:focus-visible, a:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
button:disabled, input:disabled, select:disabled, textarea:disabled,
button[aria-disabled='true'], input[aria-disabled='true'], select[aria-disabled='true'], textarea[aria-disabled='true'] {
cursor: not-allowed;
opacity: .55;
}
.app-layout { height: 100dvh; display: flex; overflow: hidden; background: var(--canvas); }
.app-sidebar { width: 236px; flex: 0 0 auto; display: flex; flex-direction: column; background: var(--sidebar); border-right: 1px solid var(--border); z-index: 30; }
.brand-row { min-height: 66px; padding: 0 18px; display: flex; align-items: center; gap: 11px; border-bottom: 1px solid var(--border); }
@@ -97,7 +108,6 @@ button { color: inherit; }
.tool-navigation a.is-active { color: var(--text); background: var(--surface); border-color: var(--border); box-shadow: 0 1px 2px rgba(20, 24, 28, .04); }
.tool-navigation a.is-active::before { position: absolute; left: -1px; width: 3px; height: 18px; content: ''; background: var(--accent); border-radius: 0 2px 2px 0; }
.tool-navigation a span { min-width: 0; overflow-wrap: anywhere; font-size: 13px; }
.tool-navigation a small { margin-left: auto; color: var(--faint); font-size: 10px; font-variant-numeric: tabular-nums; }
.empty-search { padding: 20px 10px; color: var(--muted); font-size: 12px; }
.sidebar-local { min-height: 48px; margin-top: auto; padding: 0 18px; display: flex; align-items: center; gap: 7px; color: var(--muted); border-top: 1px solid var(--border); font-size: 11px; }
@@ -121,9 +131,8 @@ button { color: inherit; }
.mode-tabs { width: fit-content; min-height: 36px; padding: 3px; display: flex; align-items: center; gap: 2px; background: var(--panel); border: 1px solid var(--border); border-radius: 7px; }
.mode-tab { min-height: 28px; padding: 0 10px; color: var(--muted); background: transparent; border: 0; border-radius: 5px; cursor: pointer; font-size: 12px; }
.mode-tab:hover { color: var(--text); }
.mode-tab:hover:not(:disabled) { color: var(--text); }
.mode-tab.is-active { color: var(--text); background: var(--surface); box-shadow: 0 0 0 1px var(--border); }
.mode-tab:disabled { cursor: not-allowed; opacity: .55; }
.tool-controls { margin-bottom: 14px; display: flex; align-items: center; flex-wrap: wrap; gap: 10px; }
.control-spacer, .action-spacer { flex: 1; }
.compact-field { display: inline-flex; align-items: center; gap: 8px; color: var(--muted); font-size: 12px; }
@@ -132,6 +141,7 @@ button { color: inherit; }
.text-input { width: 100%; padding: 0 10px; }
.text-input:focus, .select-input:focus, .compact-field select:focus { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 13%, transparent); }
.check-field { display: inline-flex; align-items: center; gap: 7px; color: var(--muted); cursor: pointer; font-size: 12px; }
.check-field:has(input:disabled) { color: var(--faint); cursor: not-allowed; }
.check-field input { width: 16px; height: 16px; margin: 0; accent-color: var(--accent); }
.editor-grid { display: grid; grid-template-columns: minmax(0, 1fr) 38px minmax(0, 1fr); gap: 13px; align-items: center; }
@@ -155,18 +165,17 @@ button { color: inherit; }
.syntax-comment { color: var(--syntax-comment); font-style: italic; }
.syntax-meta { color: var(--syntax-meta); }
.swap-button { width: 32px; height: 32px; padding: 0; display: grid; place-items: center; justify-self: center; color: var(--muted); background: var(--surface); border: 1px solid var(--border-strong); border-radius: 50%; cursor: pointer; }
.swap-button:hover { color: var(--accent); border-color: var(--accent); }
.swap-button:disabled { cursor: not-allowed; opacity: .45; }
.swap-button:hover:not(:disabled) { color: var(--accent); border-color: var(--accent); }
.action-row { min-height: 36px; margin-top: 14px; display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.action-button { min-height: 34px; padding: 0 12px; display: inline-flex; align-items: center; justify-content: center; gap: 7px; color: var(--text); background: var(--surface); border: 1px solid var(--border-strong); border-radius: 6px; cursor: pointer; font-size: 12px; font-weight: 600; }
.action-button:hover { border-color: var(--text); }
.action-button:hover:not(:disabled):not(.disabled) { border-color: var(--text); }
.action-button.primary { color: var(--primary-text); background: var(--primary); border-color: var(--primary); }
.action-button.primary:hover { background: var(--primary-hover); border-color: var(--primary-hover); }
.action-button.primary:hover:not(:disabled):not(.disabled) { background: var(--primary-hover); border-color: var(--primary-hover); }
.action-button.ghost { color: var(--muted); background: transparent; border-color: transparent; }
.action-button.ghost:hover { color: var(--text); background: var(--panel); border-color: var(--border); }
.action-button.ghost:hover:not(:disabled):not(.disabled) { color: var(--text); background: var(--panel); border-color: var(--border); }
.action-button.danger { color: var(--danger); }
.action-button:disabled, .action-button.disabled { cursor: not-allowed; opacity: .5; }
.action-button.disabled { cursor: not-allowed; opacity: .55; }
.privacy-note { min-height: 42px; margin-top: 18px; padding: 9px 13px; display: flex; align-items: center; gap: 9px; color: var(--muted); background: var(--info-soft); border-radius: 6px; font-size: 11px; }
.privacy-note strong { color: var(--text); }
.status-message { min-height: 38px; margin-top: 12px; padding: 9px 11px; display: flex; align-items: flex-start; gap: 8px; border-radius: 6px; font-size: 12px; }
@@ -187,8 +196,8 @@ button { color: inherit; }
.single-editor-layout { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }
.single-editor-layout .editor-panel textarea { min-height: 290px; }
.upload-zone { min-height: 170px; padding: 24px; display: grid; place-items: center; text-align: center; color: var(--muted); background: var(--panel); border: 1px dashed var(--border-strong); border-radius: 7px; cursor: pointer; }
.upload-zone:hover, .upload-zone.is-dragging { color: var(--text); border-color: var(--accent); background: var(--accent-soft); }
.upload-zone { position: relative; min-height: 170px; padding: 24px; display: grid; place-items: center; overflow: hidden; text-align: center; color: var(--muted); background-color: var(--panel); background-image: none; border: 1px dashed var(--border-strong); border-radius: 7px; cursor: pointer; }
.upload-zone:hover, .upload-zone:focus-within, .upload-zone.is-dragging { color: var(--text); background-color: var(--accent-soft); background-image: none; border-color: var(--accent); }
.upload-zone input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.sr-only-file { position: absolute; width: 1px; height: 1px; overflow: hidden; opacity: 0; pointer-events: none; }
.upload-zone strong { display: block; margin-top: 8px; color: var(--text); font-size: 13px; }
@@ -202,15 +211,17 @@ button { color: inherit; }
.size-option:has(input:checked) { color: var(--text); border-color: var(--accent); background: var(--accent-soft); }
.size-option input { margin: 0; accent-color: var(--accent); }
.file-meta { margin-top: 12px; color: var(--muted); font-size: 11px; }
.compact-upload { min-height: 138px; }
.compact-upload { min-height: 138px; margin-bottom: 16px; }
.firmware-summary { min-height: 58px; margin-bottom: 16px; padding: 10px 12px; display: flex; align-items: center; gap: 8px; background: var(--panel); border: 1px solid var(--border); border-radius: 7px; }
.firmware-summary > div { min-width: 0; margin-right: auto; }
.firmware-summary strong, .firmware-summary span { display: block; overflow-wrap: anywhere; }
.firmware-summary strong { font-size: 12px; font-weight: 600; }
.firmware-summary span { margin-top: 3px; color: var(--muted); font-size: 11px; }
.crc-config { display: grid; grid-template-columns: minmax(190px, 1.35fr) repeat(4, minmax(110px, 1fr)) auto auto; gap: 10px; align-items: end; }
.crc-config { display: grid; grid-template-columns: minmax(190px, 1.35fr) minmax(96px, .65fr) repeat(3, minmax(145px, 1fr)); gap: 10px; align-items: end; }
.parameter-field { min-width: 0; display: grid; gap: 6px; color: var(--muted); font-size: 11px; font-weight: 600; }
.parameter-field .select-input, .parameter-field .text-input { width: 100%; font-size: 12px; font-weight: 400; }
.crc-config .parameter-field > span { white-space: nowrap; }
.crc-reflection-options { grid-column: 1 / -1; min-height: 34px; display: flex; align-items: center; flex-wrap: wrap; column-gap: 22px; row-gap: 8px; }
.crc-check { min-height: 34px; white-space: nowrap; }
.crc-results { margin-top: 16px; }
.crc-total { min-height: 58px; padding: 10px 13px; display: flex; align-items: center; gap: 14px; color: var(--muted); background: var(--accent-soft); border: 1px solid color-mix(in srgb, var(--accent) 24%, var(--border)); border-radius: 7px; font-size: 11px; }
@@ -272,12 +283,12 @@ button { color: inherit; }
.row-actions { display: flex; gap: 3px; }
.row-action { width: 30px; height: 30px; padding: 0; display: grid; place-items: center; color: var(--muted); background: transparent; border: 1px solid transparent; border-radius: 5px; cursor: pointer; }
.row-action:hover:not(:disabled) { color: var(--text); background: var(--panel); border-color: var(--border); }
.row-action:disabled { opacity: .3; cursor: default; }
.row-action:disabled { opacity: .55; cursor: not-allowed; }
.save-state { margin-top: 14px; }
@media (max-width: 1040px) {
.crc-config { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.crc-config .preset-field { grid-column: 1 / -1; }
.crc-config .preset-field, .crc-config .crc-reflection-options { grid-column: 1 / -1; }
}
@media (max-width: 800px) {