feat: 实现管理后台 W1-W3 假数据界面

This commit is contained in:
Nixevol
2026-09-30 07:02:33 +08:00
parent 8dde564517
commit 1cff321f2a
33 changed files with 4773 additions and 31 deletions
+119
View File
@@ -0,0 +1,119 @@
<script setup lang="ts">
import { onMounted, reactive, ref } from "vue";
import {
NButton,
NDescriptions,
NDescriptionsItem,
NForm,
NFormItem,
NInput,
NSpace,
NSpin,
NTabPane,
NTabs,
NText,
} from "naive-ui";
import PageHeader from "@/components/PageHeader.vue";
import HelpTip from "@/components/HelpTip.vue";
import { changePassword, getSettings, type RuntimeSettings } from "@/api/admin";
import { message } from "@/utils/notify";
const loading = ref(true);
const settings = ref<RuntimeSettings | null>(null);
const pwd = reactive({ old_password: "", new_password: "", confirm: "" });
const pwdLoading = ref(false);
onMounted(async () => {
try {
settings.value = await getSettings();
} finally {
loading.value = false;
}
});
async function submitPassword() {
if (pwd.new_password.length < 12) {
message.error("新密码至少 12 位");
return;
}
if (pwd.new_password !== pwd.confirm) {
message.error("两次输入的新密码不一致");
return;
}
pwdLoading.value = true;
try {
await changePassword(pwd.old_password, pwd.new_password);
message.success("管理员密码已修改");
pwd.old_password = "";
pwd.new_password = "";
pwd.confirm = "";
} finally {
pwdLoading.value = false;
}
}
</script>
<template>
<div class="page">
<PageHeader title="系统" help="管理员密码在此修改;运行参数只读,修改请改配置文件后重启。" />
<div class="page-body">
<n-tabs type="line" animated>
<n-tab-pane name="password" tab="管理员密码">
<n-form label-placement="left" label-width="100" :show-feedback="false" style="max-width: 480px">
<n-form-item label="原密码">
<n-input v-model:value="pwd.old_password" type="password" show-password-on="click" />
</n-form-item>
<n-form-item>
<template #label>
新密码
<HelpTip>至少 12 位,且不能以 nst_ 开头(与端登录密码规则一致的安全要求)。</HelpTip>
</template>
<n-input v-model:value="pwd.new_password" type="password" show-password-on="click" />
</n-form-item>
<n-form-item label="确认新密码">
<n-input v-model:value="pwd.confirm" type="password" show-password-on="click" />
</n-form-item>
<n-space>
<n-button type="primary" :loading="pwdLoading" @click="submitPassword">修改密码</n-button>
</n-space>
</n-form>
</n-tab-pane>
<n-tab-pane name="settings" tab="运行参数(只读)">
<n-spin :show="loading">
<template v-if="settings">
<n-descriptions label-placement="left" :column="2" bordered size="small" style="margin-bottom: 16px">
<n-descriptions-item label="listen">{{ settings.listen }}</n-descriptions-item>
<n-descriptions-item label="admin_listen">{{ settings.admin_listen || "(空,与端共用)" }}</n-descriptions-item>
<n-descriptions-item label="会话闲置天数">{{ settings.session_idle_days }}</n-descriptions-item>
<n-descriptions-item label="记录保留天数">{{ settings.record_retention_days }}</n-descriptions-item>
<n-descriptions-item label="防重小时数">{{ settings.idempotency_hours }}</n-descriptions-item>
<n-descriptions-item label="回执保留天数">{{ settings.receipt_retention_days }}</n-descriptions-item>
<n-descriptions-item label="SQLite synchronous">{{ settings.sqlite_synchronous }}</n-descriptions-item>
</n-descriptions>
<n-text strong style="display: block; margin-bottom: 8px">limits</n-text>
<n-descriptions label-placement="left" :column="2" bordered size="small">
<n-descriptions-item v-for="(v, k) in settings.limits" :key="k" :label="String(k)">
{{ v }}
</n-descriptions-item>
</n-descriptions>
</template>
</n-spin>
</n-tab-pane>
</n-tabs>
</div>
</div>
</template>
<style scoped>
.page {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
}
.page-body {
flex: 1;
overflow: auto;
padding: 16px;
}
</style>