feat(settings): implement system settings

This commit is contained in:
yelan
2026-08-27 16:49:10 +08:00
parent ac8eff5286
commit 74df2ed741
7 changed files with 764 additions and 9 deletions
@@ -1,12 +1,136 @@
<script setup lang="ts">
import PagePlaceholder from '@/components/PagePlaceholder.vue'
import { onMounted, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
import EmbedSettingsCard from './components/EmbedSettingsCard.vue'
import SignatureSettingsCard from './components/SignatureSettingsCard.vue'
import SmsSettingsCard from './components/SmsSettingsCard.vue'
import TabletDevicesCard from './components/TabletDevicesCard.vue'
import {
defaultSmsChannel,
mockSignatureSettings,
mockTabletDevices,
smsChannelOptions,
} from './mock'
import type { SettingToggleKey, SignatureSettings, SmsChannel, TabletDevice } from './types'
const loading = ref(true)
const signatureSettings = reactive<SignatureSettings>({ ...mockSignatureSettings })
const smsChannel = ref<SmsChannel>(defaultSmsChannel)
const tabletDevices = ref<TabletDevice[]>([])
async function loadSettings() {
loading.value = true
await Promise.resolve()
tabletDevices.value = mockTabletDevices.map((device) => ({ ...device }))
loading.value = false
}
function updateLinkExpireHours(value: number) {
signatureSettings.linkExpireHours = value
}
function toggleSetting(key: SettingToggleKey) {
signatureSettings[key] = !signatureSettings[key]
if (key === 'caCertificate' && signatureSettings.caCertificate) {
ElMessage.info('已开启 CA 扩展位(当前版本未启用)')
return
}
ElMessage.info('设置已更新')
}
function updateSmsChannel(value: SmsChannel) {
smsChannel.value = value
}
function sendTestSms() {
ElMessage.success('测试短信已发送至 138****5678')
}
function reconnectDevice(device: TabletDevice) {
if (device.status === 'connected') {
ElMessage.success('已重新连接')
return
}
ElMessage.info('正在重连…')
}
function copyEmbedUrl() {
ElMessage.success('原型演示:已复制嵌入 URL')
}
function rotateKey() {
ElMessage.success('原型演示:密钥轮换成功')
}
onMounted(loadSettings)
</script>
<template>
<PagePlaceholder
group="管理"
title="系统设置"
icon="⚙"
description="系统设置页面占位,待根据 Web 端需求实现。"
/>
<section class="settings-page">
<div v-if="loading" class="loading-grid" aria-label="正在加载系统设置">
<span v-for="index in 4" :key="index" />
</div>
<div v-else class="settings-grid">
<SignatureSettingsCard
:settings="signatureSettings"
@update:link-expire-hours="updateLinkExpireHours"
@toggle="toggleSetting"
/>
<SmsSettingsCard
:channel="smsChannel"
:channel-options="smsChannelOptions"
@update:channel="updateSmsChannel"
@test="sendTestSms"
/>
<TabletDevicesCard :devices="tabletDevices" @reconnect="reconnectDevice" />
<EmbedSettingsCard @copy="copyEmbedUrl" @rotate-key="rotateKey" />
</div>
</section>
</template>
<style scoped>
.settings-page {
width: 100%;
max-width: 1440px;
margin: 0 auto;
}
.settings-grid,
.loading-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16px;
}
.loading-grid span {
display: block;
height: 240px;
background: linear-gradient(90deg, #edf3f5 25%, #f7fafb 37%, #edf3f5 63%);
background-size: 400% 100%;
border-radius: var(--r);
box-shadow: var(--sh);
animation: skeleton-shimmer 1.4s ease infinite;
}
@keyframes skeleton-shimmer {
0% {
background-position: 100% 0;
}
100% {
background-position: -100% 0;
}
}
@media (max-width: 1200px) {
.settings-grid,
.loading-grid {
grid-template-columns: 1fr;
}
}
</style>