批量修复问题

This commit is contained in:
扫地僧 2026-04-02 00:05:07 +08:00
parent 7ad314ff48
commit 1bfa019634
7 changed files with 1122 additions and 768 deletions

1
components.d.ts vendored
View File

@ -22,6 +22,7 @@ declare module 'vue' {
ElCard: typeof import('element-plus/es')['ElCard']
ElCascader: typeof import('element-plus/es')['ElCascader']
ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup']
ElCol: typeof import('element-plus/es')['ElCol']
ElColorPicker: typeof import('element-plus/es')['ElColorPicker']
ElContainer: typeof import('element-plus/es')['ElContainer']

View File

@ -13,10 +13,6 @@
<el-switch v-model="otherForm.allowRegister" />
<span class="form-tip">允许用户在前台注册账号</span>
</el-form-item>
<el-form-item label="验证码">
<el-switch v-model="otherForm.captchaEnabled" />
<span class="form-tip">登录注册等操作需要验证码</span>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="saveOtherSettings">保存设置</el-button>
<el-button @click="resetOtherForm">重置</el-button>

File diff suppressed because it is too large Load Diff

View File

@ -98,12 +98,11 @@
/>
</el-form-item>
<el-form-item label="平台端显示" prop="is_platform">
<el-switch
v-model="currentMenu.is_platform"
:active-value="1"
:inactive-value="0"
/>
<el-form-item label="菜单显示" prop="views">
<el-checkbox-group v-model="currentMenu.views" class="views-inline">
<el-checkbox :value="1" label="平台端" />
<el-checkbox :value="2" label="租户端" />
</el-checkbox-group>
</el-form-item>
<el-form-item label="权限标识" prop="permission">
@ -138,7 +137,7 @@ interface Menu {
sort: number;
status: 0 | 1;
is_visible: 0 | 1;
is_platform: 0 | 1;
views: number[];
type: 1 | 2 | 3;
permission: string;
children?: Menu[];
@ -183,7 +182,7 @@ const currentMenu = ref<Partial<Menu>>({
sort: 0,
status: 1,
is_visible: 1,
is_platform: 1,
views: [1],
type: 1,
permission: '',
});
@ -253,7 +252,7 @@ watch(() => props.menu, (newMenu) => {
sort: 0,
status: 1,
is_visible: 1,
is_platform: 1,
views: [1],
type: 1,
permission: '',
};
@ -291,7 +290,7 @@ watch(() => props.visible, (newVisible) => {
sort: 0,
status: 1,
is_visible: 1,
is_platform: 1,
views: [1],
type: 1,
permission: '',
};
@ -351,6 +350,7 @@ const formRules = ref({
}
],
sort: [{ required: true, message: "请输入排序号", trigger: "blur" }],
views: [{ required: true, message: "请选择菜单显示端", trigger: "change" }],
});
//
@ -363,11 +363,23 @@ const cascaderProps = ref({
});
const getMenuSideLabel = (menu: any) => {
return Number(menu?.is_platform) === 1 ? "平台端" : "租户端";
const views = Array.isArray(menu?.views) ? menu.views : [];
const hasP = views.includes(1);
const hasT = views.includes(2);
if (hasP && hasT) return "双端";
if (hasP) return "平台端";
if (hasT) return "租户端";
return "未设置";
};
const getMenuSideTagType = (menu: any) => {
return Number(menu?.is_platform) === 1 ? "primary" : "warning";
const views = Array.isArray(menu?.views) ? menu.views : [];
const hasP = views.includes(1);
const hasT = views.includes(2);
if (hasP && hasT) return "success";
if (hasP) return "primary";
if (hasT) return "warning";
return "info";
};
//
@ -470,4 +482,10 @@ const handleSave = async () => {
:deep(.el-form-item) {
margin-bottom: 16px;
}
.views-inline{
display: flex;
align-items: center;
gap: 14px;
}
</style>

View File

@ -95,10 +95,16 @@
</template>
</el-table-column>
<el-table-column prop="is_platform" label="平台端" width="100" align="center">
<el-table-column prop="views" label="菜单显示" width="180" align="center">
<template #default="scope">
<el-tag :type="scope.row.is_platform === 1 ? 'success' : 'info'">
{{ scope.row.is_platform === 1 ? "是" : "否" }}
<el-tag v-if="Array.isArray(scope.row.views) && scope.row.views.includes(1)" type="primary" style="margin-right:6px;">
平台端
</el-tag>
<el-tag v-if="Array.isArray(scope.row.views) && scope.row.views.includes(2)" type="warning">
租户端
</el-tag>
<el-tag v-if="!Array.isArray(scope.row.views) || scope.row.views.length === 0" type="info">
未设置
</el-tag>
</template>
</el-table-column>
@ -197,7 +203,7 @@ interface Menu {
sort: number;
status: 0 | 1;
is_visible?: 0 | 1;
is_platform?: 0 | 1;
views?: number[];
type: 1 | 2 | 3; // 1: 2: 3:
permission: string;
children?: Menu[];

View File

@ -0,0 +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>

View File

@ -0,0 +1,60 @@
<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-tabs>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import platformSettings from "./components/platformSettings.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>