Files
frontend/src/styles/common.css
NanamiAdmin 3570054586 feat(settings): add settings page with server, watchdog and notification config
- Add new Settings view with form controls for server, watchdog and notification settings
- Implement API endpoints for getting and saving settings
- Add settings route and sidebar navigation item
- Update button styles to include text color variable
- Change default app target to local development address
2026-04-29 10:46:08 +08:00

611 lines
12 KiB
CSS

.page-header {
margin-bottom: 24px;
}
.page-header h2 {
font-family: 'SF Pro Display', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 40px;
font-weight: 600;
line-height: 1.10;
color: var(--text-color);
margin: 0;
letter-spacing: normal;
transition: color 0.3s;
}
.card {
background: var(--card-bg);
border-radius: 8px;
padding: 20px;
box-shadow: var(--card-shadow);
transition: background-color 0.3s;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.card-header h3 {
font-family: 'SF Pro Display', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 21px;
font-weight: 700;
line-height: 1.19;
letter-spacing: 0.231px;
color: var(--text-color);
margin: 0;
transition: color 0.3s;
}
.card-body {
display: flex;
flex-direction: column;
gap: 12px;
}
.card-footer {
display: flex;
gap: 8px;
}
.form {
display: flex;
flex-direction: column;
gap: 16px;
}
.form-group {
display: flex;
flex-direction: column;
gap: 8px;
}
.form-group label {
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 14px;
font-weight: 600;
line-height: 1.29;
letter-spacing: -0.224px;
color: var(--text-secondary);
}
.form-group input,
.form-group select {
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
padding: 10px 14px;
border: 3px solid var(--border-color);
border-radius: 11px;
font-size: 17px;
line-height: 1.47;
letter-spacing: -0.374px;
background: var(--surface-light);
color: var(--text-color);
transition: background-color 0.3s, color 0.3s, border-color 0.3s;
}
.form-group input:focus,
.form-group select:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px var(--focus-ring);
}
.form-group input:disabled {
opacity: 0.48;
cursor: not-allowed;
}
.form-group.checkbox-group {
flex-direction: row;
align-items: center;
gap: 8px;
}
.form-group.checkbox-group input {
width: auto;
}
.empty-state {
text-align: center;
padding: 60px 20px;
color: var(--text-tertiary);
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 17px;
line-height: 1.47;
letter-spacing: -0.374px;
}
.action-btn {
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
padding: 8px 15px;
border: none;
border-radius: 8px;
font-size: 17px;
font-weight: 400;
line-height: 2.41;
cursor: pointer;
transition: all 0.3s;
}
.delete-btn {
background: var(--status-stopped);
color: white;
border-radius: 8px;
}
.delete-btn:hover {
opacity: 0.85;
}
.edit-btn {
background: var(--surface-light);
color: var(--text-color);
border-radius: 8px;
}
.edit-btn:hover {
background: var(--surface-hover);
}
.start-btn {
background: var(--primary-color);
color: white;
border-radius: 8px;
}
.start-btn:hover {
background: var(--primary-hover);
}
.stop-btn {
background: var(--status-stopped);
color: white;
border-radius: 8px;
}
.stop-btn:hover {
opacity: 0.85;
}
.add-btn {
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
padding: 8px 15px;
background: var(--primary-color);
color: white;
border: none;
border-radius: 980px;
font-size: 14px;
font-weight: 400;
line-height: 1.43;
letter-spacing: -0.224px;
cursor: pointer;
transition: all 0.3s;
}
.add-btn:hover {
background: var(--primary-hover);
}
.form-actions {
display: flex;
gap: 12px;
margin-top: 8px;
}
.cancel-btn,
.submit-btn {
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
flex: 1;
padding: 8px 15px;
border: none;
border-radius: 8px;
font-size: 17px;
font-weight: 400;
line-height: 2.41;
cursor: pointer;
transition: all 0.3s;
}
.cancel-btn {
background: var(--surface-light);
color: var(--text-color);
border: 3px solid var(--border-color);
}
.cancel-btn:hover {
background: var(--surface-hover);
}
.submit-btn {
background: var(--primary-color);
color: white;
}
.submit-btn:hover:not(:disabled) {
background: var(--primary-hover);
}
.submit-btn:disabled {
opacity: 0.48;
cursor: not-allowed;
}
.info-row {
display: flex;
justify-content: space-between;
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.29;
letter-spacing: -0.224px;
}
.info-row .label {
color: var(--text-tertiary);
}
.info-row .value {
color: var(--text-color);
font-weight: 500;
transition: color 0.3s;
}
.info-item {
display: flex;
justify-content: space-between;
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.29;
letter-spacing: -0.224px;
}
.info-label {
color: var(--text-tertiary);
font-weight: 500;
}
.info-value {
color: var(--text-color);
font-weight: 500;
text-align: right;
word-break: break-all;
transition: color 0.3s;
}
.status-badge {
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
padding: 4px 12px;
border-radius: 980px;
font-size: 12px;
font-weight: 600;
line-height: 1.33;
letter-spacing: -0.12px;
}
.status-badge.running {
background: var(--status-running-bg);
color: var(--status-running);
}
.status-badge.stopped {
background: var(--status-stopped-bg);
color: var(--status-stopped);
}
.status-badge.active {
background: var(--status-running-bg);
color: var(--status-running);
}
.status-badge.inactive {
background: var(--status-stopped-bg);
color: var(--status-stopped);
}
.type-badge {
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
display: inline-block;
padding: 2px 8px;
border-radius: 980px;
font-size: 12px;
font-weight: 600;
line-height: 1.33;
letter-spacing: -0.12px;
transition: background-color 0.3s, color 0.3s;
}
.type-badge.superuser {
background: var(--type-superuser-bg);
color: var(--type-superuser-color);
}
.type-badge.admin {
background: var(--type-admin-bg);
color: var(--type-admin-color);
}
.type-badge.visitor {
background: var(--type-visitor-bg);
color: var(--type-visitor-color);
}
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(4px);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal {
background: var(--card-bg);
border-radius: 12px;
padding: 24px;
width: 400px;
box-shadow: var(--card-shadow);
transition: background-color 0.3s;
}
.modal h3 {
font-family: 'SF Pro Display', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 21px;
font-weight: 700;
line-height: 1.19;
letter-spacing: 0.231px;
color: var(--text-color);
margin: 0 0 20px 0;
transition: color 0.3s;
}
.log-list {
display: flex;
flex-direction: column;
gap: 8px;
}
.log-item {
display: flex;
gap: 12px;
padding: 12px;
background: var(--surface-light);
border-radius: 8px;
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, monospace;
font-size: 14px;
line-height: 1.29;
letter-spacing: -0.224px;
}
.log-time {
color: var(--text-tertiary);
min-width: 160px;
}
.log-level {
min-width: 70px;
font-weight: 600;
text-align: center;
padding: 2px 8px;
border-radius: 980px;
}
.log-level.DEBUG {
color: var(--log-debug-color);
background: var(--log-debug-bg);
}
.log-level.INFO {
color: var(--log-info-color);
background: var(--log-info-bg);
}
.log-level.WARN {
color: var(--log-warn-color);
background: var(--log-warn-bg);
}
.log-level.ERROR {
color: var(--log-error-color);
background: var(--log-error-bg);
}
.log-level.FATAL {
color: var(--log-fatal-color);
background: var(--log-fatal-bg);
}
.log-message {
color: var(--text-color);
flex: 1;
word-break: break-all;
transition: color 0.3s;
}
.avatar {
width: 48px;
height: 48px;
border-radius: 50%;
background: var(--primary-color);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-family: 'SF Pro Display', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 600;
font-size: 18px;
}
.common-btn {
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
padding: 8px 15px;
background: var(--surface-light);
color: var(--text-color);
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 17px;
font-weight: 400;
line-height: 2.41;
transition: all 0.3s;
}
.common-btn:hover {
background: var(--surface-hover);
}
.config-item {
display: flex;
justify-content: space-between;
padding: 12px;
background: var(--surface-light);
border-radius: 8px;
}
.config-key {
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.29;
letter-spacing: -0.224px;
color: var(--text-tertiary);
font-weight: 500;
}
.config-value {
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.29;
letter-spacing: -0.224px;
color: var(--text-color);
transition: color 0.3s;
}
.proxy-item {
display: flex;
flex-direction: column;
gap: 12px;
padding: 12px;
background: var(--surface-light);
border-radius: 8px;
}
.proxy-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.proxy-name {
font-family: 'SF Pro Display', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 18px;
font-weight: 600;
line-height: 1.14;
letter-spacing: 0.196px;
color: var(--text-color);
transition: color 0.3s;
}
.proxy-actions-right {
display: flex;
align-items: center;
gap: 12px;
}
.proxy-type {
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
display: inline-block;
padding: 4px 12px;
border-radius: 980px;
font-size: 12px;
font-weight: 600;
line-height: 1.33;
letter-spacing: -0.12px;
background: var(--status-running-bg);
color: var(--primary-color);
text-transform: uppercase;
}
.proxy-details {
display: flex;
flex-direction: column;
gap: 8px;
padding-left: 12px;
}
.proxy-detail {
display: flex;
justify-content: space-between;
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 14px;
line-height: 1.29;
letter-spacing: -0.224px;
}
.detail-key {
color: var(--text-tertiary);
}
.detail-value {
color: var(--text-color);
transition: color 0.3s;
}
.section {
background: var(--card-bg);
border-radius: 8px;
padding: 20px;
box-shadow: var(--card-shadow);
transition: background-color 0.3s;
}
.section h3 {
font-family: 'SF Pro Display', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 21px;
font-weight: 700;
line-height: 1.19;
letter-spacing: 0.231px;
color: var(--text-color);
margin: 0 0 16px 0;
transition: color 0.3s;
}
.logs-container {
max-height: 400px;
overflow-y: auto;
}
.filter-controls select {
font-family: 'SF Pro Text', 'SF Pro Icons', 'Helvetica Neue', Helvetica, Arial, sans-serif;
padding: 0px 14px;
border: 3px solid var(--border-color);
border-radius: 11px;
font-size: 17px;
line-height: 1.47;
letter-spacing: -0.374px;
background: var(--surface-light);
color: var(--text-color);
cursor: pointer;
transition: background-color 0.3s, color 0.3s, border-color 0.3s;
}
.filter-controls select:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px var(--focus-ring);
}
.proxy-actions {
display: flex;
gap: 8px;
}
.proxy-actions .common-btn {
padding: 6px 12px;
font-size: 12px;
}