feat: Admin-Sicht System-Zeit + TZ-Liste in README/.env.example
- /api/settings gibt zusaetzlich timezone, timezone_abbr, server_time, ntp_server zurueck (alle read-only, aus Config/ENV). - AdminView zeigt neuen Abschnitt "System-Zeit" mit Zeitzone, aktueller Server-Zeit und NTP-Server samt Hinweis "wird in der .env festgelegt". - .env.example: Liste gaengiger TZ-Werte mit Link zur IANA-Vollliste. - README.md: neuer Abschnitt "Zeitzone & NTP" mit Werte-Tabelle. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,28 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- System-Info: Zeitzone & NTP (read-only) -->
|
||||
<div class="admin-section">
|
||||
<h3>System-Zeit</h3>
|
||||
<p class="hint">Wird in der <code>.env</code> festgelegt (Keys <code>TZ</code> und <code>NTP_SERVER</code>).
|
||||
Aenderungen erfordern einen Neustart des Backends.</p>
|
||||
<div class="sysinfo">
|
||||
<div class="sysinfo-row">
|
||||
<span class="sysinfo-label">Zeitzone:</span>
|
||||
<code>{{ settings.timezone || '—' }}</code>
|
||||
<span v-if="settings.timezone_abbr" class="sysinfo-extra">({{ settings.timezone_abbr }})</span>
|
||||
</div>
|
||||
<div class="sysinfo-row">
|
||||
<span class="sysinfo-label">Aktuelle Server-Zeit:</span>
|
||||
<code>{{ formatServerTime(settings.server_time) }}</code>
|
||||
</div>
|
||||
<div class="sysinfo-row">
|
||||
<span class="sysinfo-label">NTP-Server:</span>
|
||||
<code>{{ settings.ntp_server || '(deaktiviert)' }}</code>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- System Email -->
|
||||
<div class="admin-section">
|
||||
<h3>System-E-Mail (SMTP)</h3>
|
||||
@@ -551,6 +573,17 @@ const smtpForm = ref({
|
||||
const smtpPasswordSet = ref(false)
|
||||
const onlyofficeConfigured = ref(false)
|
||||
const onlyofficeUrl = ref('')
|
||||
const settings = ref({ timezone: '', timezone_abbr: '', server_time: '', ntp_server: '' })
|
||||
|
||||
function formatServerTime(iso) {
|
||||
if (!iso) return '—'
|
||||
try {
|
||||
return new Date(iso).toLocaleString('de-DE', {
|
||||
day: '2-digit', month: '2-digit', year: 'numeric',
|
||||
hour: '2-digit', minute: '2-digit', second: '2-digit',
|
||||
})
|
||||
} catch { return iso }
|
||||
}
|
||||
const smtpTesting = ref(false)
|
||||
|
||||
// Backup & Restore
|
||||
@@ -660,6 +693,12 @@ async function loadSettings() {
|
||||
smtpPasswordSet.value = res.data.system_smtp_password_set
|
||||
onlyofficeConfigured.value = res.data.onlyoffice_configured
|
||||
onlyofficeUrl.value = res.data.onlyoffice_url || ''
|
||||
settings.value = {
|
||||
timezone: res.data.timezone || '',
|
||||
timezone_abbr: res.data.timezone_abbr || '',
|
||||
server_time: res.data.server_time || '',
|
||||
ntp_server: res.data.ntp_server || '',
|
||||
}
|
||||
} catch { /* first load, defaults */ }
|
||||
}
|
||||
|
||||
@@ -1216,6 +1255,12 @@ onMounted(() => {
|
||||
.field-row { display: flex; gap: 0.75rem; align-items: flex-end; }
|
||||
.flex-grow { flex: 1; }
|
||||
.hint { font-size: 0.85rem; color: var(--p-text-muted-color); margin: 0 0 0.75rem; }
|
||||
.hint code { background: var(--p-surface-100); padding: 0.05rem 0.35rem; border-radius: 3px; font-size: 0.8rem; }
|
||||
.sysinfo { display: flex; flex-direction: column; gap: 0.4rem; font-size: 0.875rem; }
|
||||
.sysinfo-row { display: flex; gap: 0.5rem; align-items: center; flex-wrap: wrap; }
|
||||
.sysinfo-label { min-width: 180px; color: var(--p-text-muted-color); }
|
||||
.sysinfo code { background: var(--p-surface-100); padding: 0.15rem 0.5rem; border-radius: 4px; }
|
||||
.sysinfo-extra { color: var(--p-text-muted-color); font-size: 0.8rem; }
|
||||
.invite-section { margin-top: 1.5rem; padding-top: 1rem; border-top: 1px solid var(--p-surface-200); }
|
||||
.invite-section h4 { margin: 0 0 0.25rem; font-size: 0.95rem; }
|
||||
.invite-row { display: flex; gap: 0.5rem; align-items: flex-start; }
|
||||
|
||||
Reference in New Issue
Block a user