This commit is contained in:
2026-06-24 10:04:03 +08:00
parent b103192fac
commit 0f961789dc
538 changed files with 128210 additions and 128008 deletions
File diff suppressed because it is too large Load Diff
@@ -1,182 +1,182 @@
<template>
<div class="platform-settings">
<el-form
ref="formRef"
:model="formData"
:rules="rules"
label-width="120px"
class="settings-form"
>
<el-card shadow="never" class="settings-card">
<el-form-item label="开启验证">
<el-switch v-model="formData.openVerify_enabled" />
</el-form-item>
<el-form-item label="登录验证方式" prop="use_geetest">
<el-radio-group v-model="formData.use_geetest">
<el-radio label="captcha">验证码</el-radio>
<el-radio label="sms">短信</el-radio>
<el-radio label="geetest">极验</el-radio>
<el-radio label="email">邮箱</el-radio>
</el-radio-group>
</el-form-item>
<template v-if="formData.openVerify_enabled && formData.use_geetest === 'geetest'">
<el-form-item label="geetest3ID" prop="geetest3_id">
<el-input
v-model="formData.geetest3_id"
placeholder="请输入 geetest3ID"
/>
</el-form-item>
<el-form-item label="geetest3KEY" prop="geetest3_key">
<el-input
v-model="formData.geetest3_key"
placeholder="请输入 geetest3KEY"
/>
</el-form-item>
<el-form-item label="geetest4ID" prop="geetest4_id">
<el-input
v-model="formData.geetest4_id"
placeholder="请输入 geetest4ID"
/>
</el-form-item>
<el-form-item label="geetest4KEY" prop="geetest4_key">
<el-input
v-model="formData.geetest4_key"
placeholder="请输入 geetest4KEY"
/>
</el-form-item>
</template>
</el-card>
</el-form>
<div class="footer-actions">
<el-button @click="handleReset">重置</el-button>
<el-button type="primary" :loading="submitting" @click="handleSubmit"
>保存设置</el-button
>
</div>
</div>
</template>
<script setup>
import { onMounted, reactive, ref } from "vue";
import { ElMessage } from "element-plus";
import { getVerifyInfos, saveVerifyInfos } from "@/api/sitesettings";
const STORAGE_KEY = "platform_settings_draft";
const formRef = ref();
const submitting = ref(false);
const formData = reactive({
openVerify_enabled: true,
use_geetest: "captcha",
geetest3_id: "",
geetest3_key: "",
geetest4_id: "",
geetest4_key: "",
});
const validateGeetestField = (_rule, value, callback) => {
if (formData.openVerify_enabled && formData.use_geetest === "geetest" && !String(value || "").trim()) {
callback(new Error("已启用极验时该参数不能为空"));
return;
}
callback();
};
const rules = {
geetest3_id: [{ validator: validateGeetestField, trigger: "blur" }],
geetest3_key: [{ validator: validateGeetestField, trigger: "blur" }],
geetest4_id: [{ validator: validateGeetestField, trigger: "blur" }],
geetest4_key: [{ validator: validateGeetestField, trigger: "blur" }],
};
const loadDraft = () => {
const raw = localStorage.getItem(STORAGE_KEY);
if (!raw) return;
try {
const data = JSON.parse(raw);
Object.assign(formData, data);
} catch {
// ignore invalid cache
}
};
const loadRemoteVerifyInfos = async () => {
try {
const res = await getVerifyInfos();
if (res?.code === 200 && res?.data) {
Object.assign(formData, {
openVerify_enabled: Number(res.data.openVerify_enabled ?? 1) === 1,
use_geetest: res.data.use_geetest || "captcha",
geetest3_id: res.data.geetest3_id || "",
geetest3_key: res.data.geetest3_key || "",
geetest4_id: res.data.geetest4_id || "",
geetest4_key: res.data.geetest4_key || "",
});
}
} catch {
// ignore remote errors
}
};
const saveDraft = () => {
localStorage.setItem(STORAGE_KEY, JSON.stringify(formData));
};
const handleReset = () => {
Object.assign(formData, {
openVerify_enabled: true,
use_geetest: "captcha",
geetest3_id: "",
geetest3_key: "",
geetest4_id: "",
geetest4_key: "",
});
saveDraft();
ElMessage.success("已重置");
};
const handleSubmit = async () => {
if (!formRef.value) return;
await formRef.value.validate();
submitting.value = true;
try {
await saveVerifyInfos({
openVerify_enabled: formData.openVerify_enabled ? 1 : 0,
use_geetest: formData.use_geetest,
geetest3_id: formData.geetest3_id,
geetest3_key: formData.geetest3_key,
geetest4_id: formData.geetest4_id,
geetest4_key: formData.geetest4_key,
});
saveDraft();
ElMessage.success("保存成功");
} finally {
submitting.value = false;
}
};
onMounted(() => {
loadDraft();
loadRemoteVerifyInfos();
});
</script>
<style scoped>
.platform-settings {
display: flex;
flex-direction: column;
gap: 16px;
}
.settings-card {
margin-bottom: 12px;
}
.footer-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
}
</style>
<template>
<div class="platform-settings">
<el-form
ref="formRef"
:model="formData"
:rules="rules"
label-width="120px"
class="settings-form"
>
<el-card shadow="never" class="settings-card">
<el-form-item label="开启验证">
<el-switch v-model="formData.openVerify_enabled" />
</el-form-item>
<el-form-item label="登录验证方式" prop="use_geetest">
<el-radio-group v-model="formData.use_geetest">
<el-radio label="captcha">验证码</el-radio>
<el-radio label="sms">短信</el-radio>
<el-radio label="geetest">极验</el-radio>
<el-radio label="email">邮箱</el-radio>
</el-radio-group>
</el-form-item>
<template v-if="formData.openVerify_enabled && formData.use_geetest === 'geetest'">
<el-form-item label="geetest3ID" prop="geetest3_id">
<el-input
v-model="formData.geetest3_id"
placeholder="请输入 geetest3ID"
/>
</el-form-item>
<el-form-item label="geetest3KEY" prop="geetest3_key">
<el-input
v-model="formData.geetest3_key"
placeholder="请输入 geetest3KEY"
/>
</el-form-item>
<el-form-item label="geetest4ID" prop="geetest4_id">
<el-input
v-model="formData.geetest4_id"
placeholder="请输入 geetest4ID"
/>
</el-form-item>
<el-form-item label="geetest4KEY" prop="geetest4_key">
<el-input
v-model="formData.geetest4_key"
placeholder="请输入 geetest4KEY"
/>
</el-form-item>
</template>
</el-card>
</el-form>
<div class="footer-actions">
<el-button @click="handleReset">重置</el-button>
<el-button type="primary" :loading="submitting" @click="handleSubmit"
>保存设置</el-button
>
</div>
</div>
</template>
<script setup>
import { onMounted, reactive, ref } from "vue";
import { ElMessage } from "element-plus";
import { getVerifyInfos, saveVerifyInfos } from "@/api/sitesettings";
const STORAGE_KEY = "platform_settings_draft";
const formRef = ref();
const submitting = ref(false);
const formData = reactive({
openVerify_enabled: true,
use_geetest: "captcha",
geetest3_id: "",
geetest3_key: "",
geetest4_id: "",
geetest4_key: "",
});
const validateGeetestField = (_rule, value, callback) => {
if (formData.openVerify_enabled && formData.use_geetest === "geetest" && !String(value || "").trim()) {
callback(new Error("已启用极验时该参数不能为空"));
return;
}
callback();
};
const rules = {
geetest3_id: [{ validator: validateGeetestField, trigger: "blur" }],
geetest3_key: [{ validator: validateGeetestField, trigger: "blur" }],
geetest4_id: [{ validator: validateGeetestField, trigger: "blur" }],
geetest4_key: [{ validator: validateGeetestField, trigger: "blur" }],
};
const loadDraft = () => {
const raw = localStorage.getItem(STORAGE_KEY);
if (!raw) return;
try {
const data = JSON.parse(raw);
Object.assign(formData, data);
} catch {
// ignore invalid cache
}
};
const loadRemoteVerifyInfos = async () => {
try {
const res = await getVerifyInfos();
if (res?.code === 200 && res?.data) {
Object.assign(formData, {
openVerify_enabled: Number(res.data.openVerify_enabled ?? 1) === 1,
use_geetest: res.data.use_geetest || "captcha",
geetest3_id: res.data.geetest3_id || "",
geetest3_key: res.data.geetest3_key || "",
geetest4_id: res.data.geetest4_id || "",
geetest4_key: res.data.geetest4_key || "",
});
}
} catch {
// ignore remote errors
}
};
const saveDraft = () => {
localStorage.setItem(STORAGE_KEY, JSON.stringify(formData));
};
const handleReset = () => {
Object.assign(formData, {
openVerify_enabled: true,
use_geetest: "captcha",
geetest3_id: "",
geetest3_key: "",
geetest4_id: "",
geetest4_key: "",
});
saveDraft();
ElMessage.success("已重置");
};
const handleSubmit = async () => {
if (!formRef.value) return;
await formRef.value.validate();
submitting.value = true;
try {
await saveVerifyInfos({
openVerify_enabled: formData.openVerify_enabled ? 1 : 0,
use_geetest: formData.use_geetest,
geetest3_id: formData.geetest3_id,
geetest3_key: formData.geetest3_key,
geetest4_id: formData.geetest4_id,
geetest4_key: formData.geetest4_key,
});
saveDraft();
ElMessage.success("保存成功");
} finally {
submitting.value = false;
}
};
onMounted(() => {
loadDraft();
loadRemoteVerifyInfos();
});
</script>
<style scoped>
.platform-settings {
display: flex;
flex-direction: column;
gap: 16px;
}
.settings-card {
margin-bottom: 12px;
}
.footer-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
}
</style>
@@ -1,288 +1,288 @@
<template>
<div class="storage-settings">
<el-form
ref="formRef"
:model="formData"
:rules="rules"
label-width="140px"
class="settings-form"
>
<el-card shadow="never" class="settings-card">
<template #header>
<div class="card-header">
<span>存储位置配置</span>
</div>
</template>
<el-form-item label="存储类型" prop="storage_type">
<el-radio-group v-model="formData.storage_type">
<el-radio label="local">本地存储</el-radio>
<el-radio label="qiniu">七牛云存储</el-radio>
</el-radio-group>
</el-form-item>
<template v-if="formData.storage_type === 'qiniu'">
<el-divider content-position="left">七牛云配置</el-divider>
<el-form-item label="AccessKey" prop="qiniu_access_key">
<el-input
v-model="formData.qiniu_access_key"
placeholder="请输入七牛云 AccessKey"
clearable
/>
</el-form-item>
<el-form-item label="SecretKey" prop="qiniu_secret_key">
<el-input
v-model="formData.qiniu_secret_key"
type="password"
placeholder="请输入七牛云 SecretKey"
show-password
clearable
/>
</el-form-item>
<el-form-item label="Bucket" prop="qiniu_bucket">
<el-input
v-model="formData.qiniu_bucket"
placeholder="请输入存储空间名称"
clearable
/>
</el-form-item>
<el-form-item label="CDN域名" prop="qiniu_domain">
<el-input
v-model="formData.qiniu_domain"
placeholder="请输入CDN加速域名,如:https://cdn.example.com"
clearable
>
<template #prepend>
<el-icon><Link /></el-icon>
</template>
</el-input>
<div class="form-tip">用于访问上传的文件,需要在七牛云控制台配置</div>
</el-form-item>
<el-form-item label="存储区域" prop="qiniu_region">
<el-select
v-model="formData.qiniu_region"
placeholder="请选择存储区域"
clearable
>
<el-option label="华东-浙江" value="z0" />
<el-option label="华北-河北" value="z1" />
<el-option label="华南-广东" value="z2" />
<el-option label="北美-洛杉矶" value="na0" />
<el-option label="亚太-新加坡" value="as0" />
<el-option label="华东-浙江2" value="cn-east-2" />
</el-select>
<div class="form-tip">请根据您的Bucket所在区域选择</div>
</el-form-item>
</template>
<el-alert
v-if="formData.storage_type === 'local'"
title="本地存储说明"
type="info"
:closable="false"
show-icon
>
文件将存储在服务器本地磁盘,适合小规模应用或开发测试环境
</el-alert>
<el-alert
v-if="formData.storage_type === 'qiniu'"
title="七牛云存储说明"
type="warning"
:closable="false"
show-icon
>
<p>使用七牛云存储需要:</p>
<ul style="margin: 8px 0; padding-left: 20px;">
<li>在七牛云控制台创建存储空间(Bucket)</li>
<li>获取 AccessKey 和 SecretKey(在个人中心-密钥管理)</li>
<li>配置 CDN 加速域名(在存储空间-域名管理)</li>
<li>确保域名已备案并完成 CNAME 解析</li>
</ul>
</el-alert>
</el-card>
</el-form>
<div class="footer-actions">
<el-button @click="handleReset">重置</el-button>
<el-button type="primary" :loading="submitting" @click="handleSubmit">
保存设置
</el-button>
</div>
</div>
</template>
<script setup>
import { onMounted, reactive, ref } from "vue";
import { ElMessage } from "element-plus";
import { Link } from "@element-plus/icons-vue";
import { getStorageConfig, saveStorageConfig } from "@/api/sitesettings";
const STORAGE_KEY = "storage_settings_draft";
const formRef = ref();
const submitting = ref(false);
const formData = reactive({
storage_type: "local",
qiniu_access_key: "",
qiniu_secret_key: "",
qiniu_bucket: "",
qiniu_domain: "",
qiniu_region: "",
});
const validateQiniuField = (field, fieldName) => {
return (_rule, value, callback) => {
if (
formData.storage_type === "qiniu" &&
!String(value || "").trim()
) {
callback(new Error(`${fieldName}不能为空`));
return;
}
callback();
};
};
const rules = {
qiniu_access_key: [
{ validator: validateQiniuField("qiniu_access_key", "AccessKey"), trigger: "blur" },
],
qiniu_secret_key: [
{ validator: validateQiniuField("qiniu_secret_key", "SecretKey"), trigger: "blur" },
],
qiniu_bucket: [
{ validator: validateQiniuField("qiniu_bucket", "Bucket"), trigger: "blur" },
],
qiniu_domain: [
{ validator: validateQiniuField("qiniu_domain", "CDN域名"), trigger: "blur" },
],
};
const loadDraft = () => {
const raw = localStorage.getItem(STORAGE_KEY);
if (!raw) return;
try {
const data = JSON.parse(raw);
Object.assign(formData, data);
} catch {
// ignore invalid cache
}
};
const loadRemoteConfig = async () => {
try {
const res = await getStorageConfig();
if (res?.code === 200 && res?.data) {
Object.assign(formData, {
storage_type: res.data.storage_type || "local",
qiniu_access_key: res.data.qiniu_access_key || "",
qiniu_secret_key: res.data.qiniu_secret_key || "",
qiniu_bucket: res.data.qiniu_bucket || "",
qiniu_domain: res.data.qiniu_domain || "",
qiniu_region: res.data.qiniu_region || "",
});
}
} catch (error) {
console.error("加载存储配置失败:", error);
}
};
const saveDraft = () => {
localStorage.setItem(STORAGE_KEY, JSON.stringify(formData));
};
const handleReset = () => {
Object.assign(formData, {
storage_type: "local",
qiniu_access_key: "",
qiniu_secret_key: "",
qiniu_bucket: "",
qiniu_domain: "",
qiniu_region: "",
});
saveDraft();
ElMessage.success("已重置");
};
const handleSubmit = async () => {
if (!formRef.value) return;
try {
await formRef.value.validate();
} catch {
return;
}
submitting.value = true;
try {
await saveStorageConfig({
storage_type: formData.storage_type,
qiniu_access_key: formData.qiniu_access_key || null,
qiniu_secret_key: formData.qiniu_secret_key || null,
qiniu_bucket: formData.qiniu_bucket || null,
qiniu_domain: formData.qiniu_domain || null,
qiniu_region: formData.qiniu_region || null,
});
saveDraft();
ElMessage.success("保存成功");
} catch (error) {
ElMessage.error(error?.response?.data?.msg || "保存失败");
} finally {
submitting.value = false;
}
};
onMounted(() => {
loadDraft();
loadRemoteConfig();
});
</script>
<style scoped>
.storage-settings {
display: flex;
flex-direction: column;
gap: 16px;
}
.settings-card {
margin-bottom: 12px;
}
.card-header {
font-weight: 600;
font-size: 16px;
}
.form-tip {
font-size: 12px;
color: var(--el-text-color-secondary);
margin-top: 4px;
line-height: 1.5;
}
.footer-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
}
:deep(.el-alert) {
margin-top: 16px;
}
:deep(.el-alert ul) {
list-style-type: disc;
}
:deep(.el-alert li) {
line-height: 1.8;
}
</style>
<template>
<div class="storage-settings">
<el-form
ref="formRef"
:model="formData"
:rules="rules"
label-width="140px"
class="settings-form"
>
<el-card shadow="never" class="settings-card">
<template #header>
<div class="card-header">
<span>存储位置配置</span>
</div>
</template>
<el-form-item label="存储类型" prop="storage_type">
<el-radio-group v-model="formData.storage_type">
<el-radio label="local">本地存储</el-radio>
<el-radio label="qiniu">七牛云存储</el-radio>
</el-radio-group>
</el-form-item>
<template v-if="formData.storage_type === 'qiniu'">
<el-divider content-position="left">七牛云配置</el-divider>
<el-form-item label="AccessKey" prop="qiniu_access_key">
<el-input
v-model="formData.qiniu_access_key"
placeholder="请输入七牛云 AccessKey"
clearable
/>
</el-form-item>
<el-form-item label="SecretKey" prop="qiniu_secret_key">
<el-input
v-model="formData.qiniu_secret_key"
type="password"
placeholder="请输入七牛云 SecretKey"
show-password
clearable
/>
</el-form-item>
<el-form-item label="Bucket" prop="qiniu_bucket">
<el-input
v-model="formData.qiniu_bucket"
placeholder="请输入存储空间名称"
clearable
/>
</el-form-item>
<el-form-item label="CDN域名" prop="qiniu_domain">
<el-input
v-model="formData.qiniu_domain"
placeholder="请输入CDN加速域名,如:https://cdn.example.com"
clearable
>
<template #prepend>
<el-icon><Link /></el-icon>
</template>
</el-input>
<div class="form-tip">用于访问上传的文件,需要在七牛云控制台配置</div>
</el-form-item>
<el-form-item label="存储区域" prop="qiniu_region">
<el-select
v-model="formData.qiniu_region"
placeholder="请选择存储区域"
clearable
>
<el-option label="华东-浙江" value="z0" />
<el-option label="华北-河北" value="z1" />
<el-option label="华南-广东" value="z2" />
<el-option label="北美-洛杉矶" value="na0" />
<el-option label="亚太-新加坡" value="as0" />
<el-option label="华东-浙江2" value="cn-east-2" />
</el-select>
<div class="form-tip">请根据您的Bucket所在区域选择</div>
</el-form-item>
</template>
<el-alert
v-if="formData.storage_type === 'local'"
title="本地存储说明"
type="info"
:closable="false"
show-icon
>
文件将存储在服务器本地磁盘,适合小规模应用或开发测试环境
</el-alert>
<el-alert
v-if="formData.storage_type === 'qiniu'"
title="七牛云存储说明"
type="warning"
:closable="false"
show-icon
>
<p>使用七牛云存储需要:</p>
<ul style="margin: 8px 0; padding-left: 20px;">
<li>在七牛云控制台创建存储空间(Bucket)</li>
<li>获取 AccessKey 和 SecretKey(在个人中心-密钥管理)</li>
<li>配置 CDN 加速域名(在存储空间-域名管理)</li>
<li>确保域名已备案并完成 CNAME 解析</li>
</ul>
</el-alert>
</el-card>
</el-form>
<div class="footer-actions">
<el-button @click="handleReset">重置</el-button>
<el-button type="primary" :loading="submitting" @click="handleSubmit">
保存设置
</el-button>
</div>
</div>
</template>
<script setup>
import { onMounted, reactive, ref } from "vue";
import { ElMessage } from "element-plus";
import { Link } from "@element-plus/icons-vue";
import { getStorageConfig, saveStorageConfig } from "@/api/sitesettings";
const STORAGE_KEY = "storage_settings_draft";
const formRef = ref();
const submitting = ref(false);
const formData = reactive({
storage_type: "local",
qiniu_access_key: "",
qiniu_secret_key: "",
qiniu_bucket: "",
qiniu_domain: "",
qiniu_region: "",
});
const validateQiniuField = (field, fieldName) => {
return (_rule, value, callback) => {
if (
formData.storage_type === "qiniu" &&
!String(value || "").trim()
) {
callback(new Error(`${fieldName}不能为空`));
return;
}
callback();
};
};
const rules = {
qiniu_access_key: [
{ validator: validateQiniuField("qiniu_access_key", "AccessKey"), trigger: "blur" },
],
qiniu_secret_key: [
{ validator: validateQiniuField("qiniu_secret_key", "SecretKey"), trigger: "blur" },
],
qiniu_bucket: [
{ validator: validateQiniuField("qiniu_bucket", "Bucket"), trigger: "blur" },
],
qiniu_domain: [
{ validator: validateQiniuField("qiniu_domain", "CDN域名"), trigger: "blur" },
],
};
const loadDraft = () => {
const raw = localStorage.getItem(STORAGE_KEY);
if (!raw) return;
try {
const data = JSON.parse(raw);
Object.assign(formData, data);
} catch {
// ignore invalid cache
}
};
const loadRemoteConfig = async () => {
try {
const res = await getStorageConfig();
if (res?.code === 200 && res?.data) {
Object.assign(formData, {
storage_type: res.data.storage_type || "local",
qiniu_access_key: res.data.qiniu_access_key || "",
qiniu_secret_key: res.data.qiniu_secret_key || "",
qiniu_bucket: res.data.qiniu_bucket || "",
qiniu_domain: res.data.qiniu_domain || "",
qiniu_region: res.data.qiniu_region || "",
});
}
} catch (error) {
console.error("加载存储配置失败:", error);
}
};
const saveDraft = () => {
localStorage.setItem(STORAGE_KEY, JSON.stringify(formData));
};
const handleReset = () => {
Object.assign(formData, {
storage_type: "local",
qiniu_access_key: "",
qiniu_secret_key: "",
qiniu_bucket: "",
qiniu_domain: "",
qiniu_region: "",
});
saveDraft();
ElMessage.success("已重置");
};
const handleSubmit = async () => {
if (!formRef.value) return;
try {
await formRef.value.validate();
} catch {
return;
}
submitting.value = true;
try {
await saveStorageConfig({
storage_type: formData.storage_type,
qiniu_access_key: formData.qiniu_access_key || null,
qiniu_secret_key: formData.qiniu_secret_key || null,
qiniu_bucket: formData.qiniu_bucket || null,
qiniu_domain: formData.qiniu_domain || null,
qiniu_region: formData.qiniu_region || null,
});
saveDraft();
ElMessage.success("保存成功");
} catch (error) {
ElMessage.error(error?.response?.data?.msg || "保存失败");
} finally {
submitting.value = false;
}
};
onMounted(() => {
loadDraft();
loadRemoteConfig();
});
</script>
<style scoped>
.storage-settings {
display: flex;
flex-direction: column;
gap: 16px;
}
.settings-card {
margin-bottom: 12px;
}
.card-header {
font-weight: 600;
font-size: 16px;
}
.form-tip {
font-size: 12px;
color: var(--el-text-color-secondary);
margin-top: 4px;
line-height: 1.5;
}
.footer-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
}
:deep(.el-alert) {
margin-top: 16px;
}
:deep(.el-alert ul) {
list-style-type: disc;
}
:deep(.el-alert li) {
line-height: 1.8;
}
</style>
@@ -1,80 +1,80 @@
<template>
<div class="container-box">
<div class="header-bar">
<h2>平台设置</h2>
</div>
<el-divider></el-divider>
<div class="settings-container">
<el-tabs v-model="activeTab" class="settings-tabs">
<!-- 验证开关 -->
<el-tab-pane label="验证开关" name="platform">
<platformSettings
ref="platformSettingsRef"
v-if="activeTab === 'platform'"
/>
</el-tab-pane>
<!-- 存储配置 -->
<el-tab-pane label="存储配置" name="storage">
<storageSettings
ref="storageSettingsRef"
v-if="activeTab === 'storage'"
/>
</el-tab-pane>
<!-- 通知配置 -->
<el-tab-pane label="通知配置" name="notification">
<notificationSettings
ref="notificationSettingsRef"
v-if="activeTab === 'notification'"
/>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import platformSettings from "./components/platformSettings.vue";
import storageSettings from "./components/storageSettings.vue";
import notificationSettings from "./components/notificationSettings.vue";
const activeTab = ref("platform");
</script>
<style lang="less" scoped>
.container-box {
padding: 20px;
border-radius: 4px;
}
.header-bar {
display: flex;
justify-content: space-between;
align-items: center;
color: var(--el-text-color-primary);
h2 {
margin: 0;
font-size: 18px;
font-weight: 600;
}
}
.settings-container {
margin-top: 20px;
}
.settings-tabs {
:deep(.el-tabs__header) {
margin-bottom: 20px;
}
:deep(.el-tabs__nav-wrap::after) {
height: 1px;
}
}
</style>
<template>
<div class="container-box">
<div class="header-bar">
<h2>平台设置</h2>
</div>
<el-divider></el-divider>
<div class="settings-container">
<el-tabs v-model="activeTab" class="settings-tabs">
<!-- 验证开关 -->
<el-tab-pane label="验证开关" name="platform">
<platformSettings
ref="platformSettingsRef"
v-if="activeTab === 'platform'"
/>
</el-tab-pane>
<!-- 存储配置 -->
<el-tab-pane label="存储配置" name="storage">
<storageSettings
ref="storageSettingsRef"
v-if="activeTab === 'storage'"
/>
</el-tab-pane>
<!-- 通知配置 -->
<el-tab-pane label="通知配置" name="notification">
<notificationSettings
ref="notificationSettingsRef"
v-if="activeTab === 'notification'"
/>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import platformSettings from "./components/platformSettings.vue";
import storageSettings from "./components/storageSettings.vue";
import notificationSettings from "./components/notificationSettings.vue";
const activeTab = ref("platform");
</script>
<style lang="less" scoped>
.container-box {
padding: 20px;
border-radius: 4px;
}
.header-bar {
display: flex;
justify-content: space-between;
align-items: center;
color: var(--el-text-color-primary);
h2 {
margin: 0;
font-size: 18px;
font-weight: 600;
}
}
.settings-container {
margin-top: 20px;
}
.settings-tabs {
:deep(.el-tabs__header) {
margin-bottom: 20px;
}
:deep(.el-tabs__nav-wrap::after) {
height: 1px;
}
}
</style>