first commit
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<el-form ref="contactFormRef" :model="contactForm" :rules="contactRules" label-width="120px" style="max-width: 600px">
|
||||
<el-form-item label="联系电话" prop="phone">
|
||||
<el-input v-model="contactForm.phone" placeholder="请输入联系电话" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系邮箱" prop="email">
|
||||
<el-input v-model="contactForm.email" placeholder="请输入联系邮箱" />
|
||||
</el-form-item>
|
||||
<el-form-item label="公司地址" prop="address">
|
||||
<el-input v-model="contactForm.address" placeholder="请输入公司地址" />
|
||||
</el-form-item>
|
||||
<el-form-item label="工作时间" prop="workTime">
|
||||
<el-input v-model="contactForm.workTime" placeholder="如:周一至周五 9:00-18:00" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="saveContactSettings">保存设置</el-button>
|
||||
<el-button @click="resetContactForm">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import type { FormInstance, FormRules } from "element-plus";
|
||||
|
||||
import { getCompanyInfos, saveCompanyInfos } from "@/api/sitesettings";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const contactFormRef = ref<FormInstance>();
|
||||
|
||||
const contactForm = reactive({
|
||||
phone: "",
|
||||
email: "",
|
||||
address: "",
|
||||
workTime: ""
|
||||
});
|
||||
|
||||
const contactRules: FormRules = {
|
||||
email: [{ type: "email", message: "请输入正确的邮箱地址", trigger: "blur" }]
|
||||
};
|
||||
|
||||
// 获取企业信息
|
||||
const initCompanyInfos = async () => {
|
||||
const res = await getCompanyInfos(authStore.user.tid);
|
||||
if (res.code === 200 && res.data) {
|
||||
const data = res.data;
|
||||
contactForm.phone = data.contact_phone || "";
|
||||
contactForm.email = data.contact_email || "";
|
||||
contactForm.address = data.address || "";
|
||||
contactForm.workTime = data.worktime || "";
|
||||
}
|
||||
};
|
||||
|
||||
const saveContactSettings = async () => {
|
||||
if (!contactFormRef.value) return;
|
||||
await contactFormRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
const data = {
|
||||
tid: authStore.user.tid,
|
||||
contact_phone: contactForm.phone,
|
||||
contact_email: contactForm.email,
|
||||
address: contactForm.address,
|
||||
worktime: contactForm.workTime
|
||||
};
|
||||
const res = await saveCompanyInfos(data);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("联系方式保存成功");
|
||||
} else {
|
||||
ElMessage.error(res.msg || "保存失败");
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const resetContactForm = () => {
|
||||
contactForm.phone = "";
|
||||
contactForm.email = "";
|
||||
contactForm.address = "";
|
||||
contactForm.workTime = "";
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
contactForm
|
||||
});
|
||||
|
||||
// 初始化数据
|
||||
onMounted(() => {
|
||||
initCompanyInfos();
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,102 @@
|
||||
<template>
|
||||
<el-form
|
||||
ref="legalNoticeFormRef"
|
||||
:model="formData"
|
||||
label-width="120px"
|
||||
style="max-width: 600px"
|
||||
>
|
||||
<el-form-item label="法律声明" prop="legalNotice">
|
||||
<el-input
|
||||
v-model="legalNotice"
|
||||
type="textarea"
|
||||
:rows="8"
|
||||
placeholder="请输入法律声明"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="隐私条款" prop="privacyTerms">
|
||||
<el-input
|
||||
v-model="privacyTerms"
|
||||
type="textarea"
|
||||
:rows="8"
|
||||
placeholder="请输入隐私条款"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleSaveLegalInfos">保存设置</el-button>
|
||||
<el-button @click="resetLegalNoticeForm">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import type { FormInstance, FormRules } from "element-plus";
|
||||
|
||||
import { getLegalInfos, saveLegalInfos } from "@/api/sitesettings";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const legalNoticeFormRef = ref<FormInstance>();
|
||||
|
||||
const legalNotice = ref("");
|
||||
const privacyTerms = ref("");
|
||||
|
||||
const seoForm = reactive({
|
||||
legalNotice: "",
|
||||
privacyTerms: "",
|
||||
});
|
||||
|
||||
const formData = {
|
||||
legalNotice,
|
||||
privacyTerms,
|
||||
};
|
||||
|
||||
//调用法律声明和隐私条款数据
|
||||
const initLegalInfos = async () => {
|
||||
const res = await getLegalInfos();
|
||||
if (res.code === 200 && res.data) {
|
||||
const data = res.data;
|
||||
const dataMap: Record<string, string> = {};
|
||||
data.forEach((item: any) => {
|
||||
dataMap[item.label] = item.value;
|
||||
});
|
||||
legalNotice.value = dataMap["legalNotice"] || "";
|
||||
privacyTerms.value = dataMap["privacyTerms"] || "";
|
||||
}
|
||||
};
|
||||
|
||||
const handleSaveLegalInfos = async () => {
|
||||
if (!legalNoticeFormRef.value) return;
|
||||
await legalNoticeFormRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
const data = {
|
||||
tid: authStore.user.tid,
|
||||
legalNotice: legalNotice.value,
|
||||
privacyTerms: privacyTerms.value
|
||||
};
|
||||
const res = await saveLegalInfos(data);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("保存成功");
|
||||
} else {
|
||||
ElMessage.error(res.msg || "保存失败");
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const resetLegalNoticeForm = () => {
|
||||
legalNotice.value = "";
|
||||
privacyTerms.value = "";
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
legalNotice,
|
||||
privacyTerms,
|
||||
});
|
||||
|
||||
// 初始化法律声明和隐私条款数据
|
||||
onMounted(() => {
|
||||
initLegalInfos();
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<el-form ref="formRef" :model="form" label-width="120px">
|
||||
<el-form-item label="开启验证" prop="openVerify">
|
||||
<el-switch v-model="form.openVerify" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="验证模式" prop="verifyModel">
|
||||
<el-radio-group v-model="form.verifyModel" :disabled="!form.openVerify">
|
||||
<el-radio-button value="1">图形</el-radio-button>
|
||||
<el-radio-button value="2">短信</el-radio-button>
|
||||
<el-radio-button value="3">邮箱</el-radio-button>
|
||||
<el-radio-button value="4">极验3.0</el-radio-button>
|
||||
<el-radio-button value="5">极验4.0</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<template v-if="form.verifyModel === '4'">
|
||||
<el-form-item label="极验ID" prop="geetest3ID">
|
||||
<el-input v-model="form.geetest3ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="极验KEY" prop="geetest3KEY">
|
||||
<el-input v-model="form.geetest3KEY" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<template v-if="form.verifyModel === '5'">
|
||||
<el-form-item label="极验ID" prop="geetest4ID">
|
||||
<el-input v-model="form.geetest4ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="极验KEY" prop="geetest4KEY">
|
||||
<el-input v-model="form.geetest4KEY" />
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleSave">保存</el-button>
|
||||
<el-button @click="formRef?.resetFields()">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { getVerifyInfos, saveVerifyInfos } from "@/api/sitesettings";
|
||||
|
||||
const formRef = ref();
|
||||
const form = reactive({
|
||||
openVerify: false,
|
||||
verifyModel: "1",
|
||||
geetest3ID: "",
|
||||
geetest3KEY: "",
|
||||
geetest4ID: "",
|
||||
geetest4KEY: ""
|
||||
});
|
||||
|
||||
const init = async () => {
|
||||
const { code, data } = await getVerifyInfos();
|
||||
if (code === 200 && Array.isArray(data)) {
|
||||
const formData = {};
|
||||
data.forEach(item => {
|
||||
if (item.label === 'openVerify') {
|
||||
formData[item.label] = item.value === '1';
|
||||
} else {
|
||||
formData[item.label] = item.value;
|
||||
}
|
||||
});
|
||||
|
||||
Object.assign(form, formData);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
const { code } = await saveVerifyInfos(form);
|
||||
if (code === 200) ElMessage.success("保存成功");
|
||||
};
|
||||
|
||||
init();
|
||||
|
||||
defineExpose({ form, init });
|
||||
</script>
|
||||
@@ -0,0 +1,301 @@
|
||||
<template>
|
||||
<el-form
|
||||
ref="normalFormRef"
|
||||
:model="formData"
|
||||
:rules="normalRules"
|
||||
label-width="120px"
|
||||
style="max-width: 600px"
|
||||
>
|
||||
<el-form-item label="站点名称" prop="sitename">
|
||||
<el-input v-model="sitename" placeholder="请输入站点名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="站点Logo" prop="logo">
|
||||
<el-upload
|
||||
class="logo-uploader"
|
||||
:show-file-list="false"
|
||||
:auto-upload="false"
|
||||
:on-change="handleLogoChange"
|
||||
>
|
||||
<img
|
||||
v-if="logo"
|
||||
:src="getPreviewUrl(logo)"
|
||||
class="logo-image"
|
||||
/>
|
||||
<el-icon v-else class="logo-uploader-icon"><Plus /></el-icon>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="站点Logo-浅色" prop="logow">
|
||||
<el-upload
|
||||
class="logo-uploader"
|
||||
:show-file-list="false"
|
||||
:auto-upload="false"
|
||||
:on-change="handleLogowChange"
|
||||
>
|
||||
<img
|
||||
v-if="logow"
|
||||
:src="getPreviewUrl(logow)"
|
||||
class="logo-image darkbg"
|
||||
/>
|
||||
<el-icon v-else class="logo-uploader-icon"><Plus /></el-icon>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
<el-form-item label="站点图标" prop="ico">
|
||||
<el-upload
|
||||
class="logo-uploader"
|
||||
:show-file-list="false"
|
||||
:auto-upload="false"
|
||||
:on-change="handleIconChange"
|
||||
>
|
||||
<img
|
||||
v-if="ico"
|
||||
:src="getPreviewUrl(ico)"
|
||||
class="logo-image"
|
||||
/>
|
||||
<el-icon v-else class="logo-uploader-icon"><Plus /></el-icon>
|
||||
</el-upload>
|
||||
<div class="form-tip">请上传ico格式文件</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="企业名称" prop="companyname">
|
||||
<el-input v-model="companyname" placeholder="请输入企业名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="企业介绍" prop="companyintroduction">
|
||||
<el-input v-model="companyintroduction" type="textarea" rows="5" placeholder="请输入企业介绍" />
|
||||
</el-form-item>
|
||||
<el-form-item label="站点简介" prop="description">
|
||||
<el-input v-model="description" placeholder="请输入站点简介" />
|
||||
</el-form-item>
|
||||
<el-form-item label="版权信息" prop="copyright">
|
||||
<el-input v-model="copyright" placeholder="如:© 2026 公司名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备案号 " prop="icp">
|
||||
<el-input v-model="icp" placeholder="如:苏ICP备20260000号" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleSaveNormalInfos"
|
||||
>保存设置</el-button
|
||||
>
|
||||
<el-button @click="resetnormalForm">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { Plus } from "@element-plus/icons-vue";
|
||||
import type { FormInstance, FormRules, UploadFile } from "element-plus";
|
||||
import { getNormalInfos, saveNormalInfos } from "@/api/sitesettings";
|
||||
import { uploadFile } from "@/api/file";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
|
||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
|
||||
const authStore = useAuthStore();
|
||||
|
||||
const normalFormRef = ref<FormInstance>();
|
||||
|
||||
const sitename = ref("");
|
||||
const companyname = ref("");
|
||||
const companyintroduction = ref("");
|
||||
const logo = ref("");
|
||||
const logow = ref("");
|
||||
const description = ref("");
|
||||
const copyright = ref("");
|
||||
const icp = ref("");
|
||||
const ico = ref("");
|
||||
|
||||
const formData = {
|
||||
sitename,
|
||||
companyname,
|
||||
companyintroduction,
|
||||
logo,
|
||||
logow,
|
||||
ico,
|
||||
description,
|
||||
copyright,
|
||||
icp,
|
||||
};
|
||||
|
||||
const normalRules: FormRules = {
|
||||
sitename: [{ required: true, message: "请输入站点名称", trigger: "blur" }],
|
||||
};
|
||||
|
||||
const getPreviewUrl = (url: string) => {
|
||||
const value = String(url || "").trim().replace(/\\/g, "/");
|
||||
if (!value) return "";
|
||||
if (/^(https?:\/\/|\/\/|data:|blob:)/i.test(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
const base = String(API_BASE_URL || "").replace(/\/+$/, "");
|
||||
const path = value.startsWith("/") ? value : `/${value}`;
|
||||
return `${base}${path}`;
|
||||
};
|
||||
|
||||
//调用基础数据
|
||||
const initNormalInfos = async () => {
|
||||
const res = await getNormalInfos(authStore.user.tid);
|
||||
if (res.code === 200 && res.data) {
|
||||
const data = res.data;
|
||||
sitename.value = data.sitename || "";
|
||||
companyintroduction.value = data.companyintroduction || "";
|
||||
logo.value = data.logo || "";
|
||||
logow.value = data.logow || "";
|
||||
ico.value = data.ico || "";
|
||||
description.value = data.description || "";
|
||||
copyright.value = data.copyright || "";
|
||||
icp.value = data.icp || "";
|
||||
companyname.value = data.companyname || "";
|
||||
}
|
||||
};
|
||||
|
||||
const handleLogoChange = (file: UploadFile) => {
|
||||
const uploadFormData = new FormData();
|
||||
uploadFormData.append("file", file.raw);
|
||||
uploadFormData.append("cate", "site");
|
||||
|
||||
uploadFile(uploadFormData).then((uploadRes) => {
|
||||
if (
|
||||
(uploadRes.code === 200 || uploadRes.code === 201) &&
|
||||
uploadRes.data &&
|
||||
uploadRes.data.url
|
||||
) {
|
||||
logo.value = uploadRes.data.url.replace(/\\/g, "/");
|
||||
} else {
|
||||
ElMessage.error(uploadRes.msg || "上传失败");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleLogowChange = (file: UploadFile) => {
|
||||
const uploadFormData = new FormData();
|
||||
uploadFormData.append("file", file.raw);
|
||||
uploadFormData.append("cate", "site");
|
||||
|
||||
uploadFile(uploadFormData).then((uploadRes) => {
|
||||
if (
|
||||
(uploadRes.code === 200 || uploadRes.code === 201) &&
|
||||
uploadRes.data &&
|
||||
uploadRes.data.url
|
||||
) {
|
||||
logow.value = uploadRes.data.url.replace(/\\/g, "/");
|
||||
} else {
|
||||
ElMessage.error(uploadRes.msg || "上传失败");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleSaveNormalInfos = async () => {
|
||||
if (!normalFormRef.value) return;
|
||||
await normalFormRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
const data = {
|
||||
tid: authStore.user.tid,
|
||||
sitename: sitename.value,
|
||||
companyintroduction: companyintroduction.value,
|
||||
logo: logo.value,
|
||||
logow: logow.value,
|
||||
ico: ico.value,
|
||||
description: description.value,
|
||||
companyname: companyname.value,
|
||||
copyright: copyright.value,
|
||||
icp: icp.value,
|
||||
};
|
||||
const res = await saveNormalInfos(data);
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("保存成功");
|
||||
} else {
|
||||
ElMessage.error(res.msg || "保存失败");
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleIconChange = (file: UploadFile) => {
|
||||
const uploadFormData = new FormData();
|
||||
uploadFormData.append("file", file.raw);
|
||||
uploadFormData.append("cate", "site");
|
||||
|
||||
uploadFile(uploadFormData).then((uploadRes) => {
|
||||
if ((uploadRes.code === 200 || uploadRes.code === 201) && uploadRes.data?.url) {
|
||||
ico.value = uploadRes.data.url.replace(/\\/g, "/");
|
||||
} else {
|
||||
ElMessage.error(uploadRes.msg || "上传失败");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const resetnormalForm = () => {
|
||||
sitename.value = "";
|
||||
companyname.value = "";
|
||||
companyintroduction.value = "";
|
||||
logo.value = "";
|
||||
logow.value = "";
|
||||
ico.value = "";
|
||||
description.value = "";
|
||||
copyright.value = "";
|
||||
icp.value = "";
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
sitename,
|
||||
companyname,
|
||||
companyintroduction,
|
||||
logo,
|
||||
logow,
|
||||
ico,
|
||||
description,
|
||||
copyright,
|
||||
icp,
|
||||
});
|
||||
|
||||
// 初始化基础数据
|
||||
onMounted(() => {
|
||||
initNormalInfos();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.darkbg {
|
||||
background-color: #efefef;
|
||||
}
|
||||
|
||||
.form-tip{
|
||||
margin-left: 20px;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.logo-uploader {
|
||||
:deep(.el-upload) {
|
||||
border: 1px dashed #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: all 0.3s;
|
||||
|
||||
&:hover {
|
||||
border-color: #3973ff;
|
||||
}
|
||||
}
|
||||
|
||||
.logo-uploader-icon {
|
||||
font-size: 28px;
|
||||
color: #8c939d;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.logo-image {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
object-fit: contain;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<el-form
|
||||
ref="otherFormRef"
|
||||
:model="otherForm"
|
||||
label-width="120px"
|
||||
style="max-width: 600px"
|
||||
>
|
||||
<el-form-item label="开启维护模式">
|
||||
<el-switch v-model="otherForm.maintenanceMode" />
|
||||
<span class="form-tip">开启后,前台将显示维护中页面</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="开启注册">
|
||||
<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>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import type { FormInstance } from "element-plus";
|
||||
|
||||
const otherFormRef = ref<FormInstance>();
|
||||
|
||||
const otherForm = reactive({
|
||||
maintenanceMode: false,
|
||||
allowRegister: false,
|
||||
captchaEnabled: true
|
||||
});
|
||||
|
||||
const saveOtherSettings = () => {
|
||||
// TODO: 保存其他设置
|
||||
ElMessage.success("其他设置保存成功");
|
||||
};
|
||||
|
||||
const resetOtherForm = () => {
|
||||
otherForm.maintenanceMode = false;
|
||||
otherForm.allowRegister = false;
|
||||
otherForm.captchaEnabled = true;
|
||||
};
|
||||
|
||||
defineExpose({
|
||||
otherForm
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.form-tip {
|
||||
margin-left: 10px;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<el-form
|
||||
ref="seoFormRef"
|
||||
:model="seoForm"
|
||||
:rules="seoRules"
|
||||
label-width="120px"
|
||||
style="max-width: 600px"
|
||||
>
|
||||
<el-form-item label="SEO标题" prop="seoTitle">
|
||||
<el-input v-model="seoForm.seoTitle" placeholder="请输入SEO标题" />
|
||||
</el-form-item>
|
||||
<el-form-item label="SEO关键词" prop="seoKeywords">
|
||||
<el-input
|
||||
v-model="seoForm.seoKeywords"
|
||||
placeholder="多个关键词用逗号分隔"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="SEO描述" prop="seoDescription">
|
||||
<el-input
|
||||
v-model="seoForm.seoDescription"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入SEO描述"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="saveSeoSettings">保存设置</el-button>
|
||||
<el-button @click="resetSeoForm">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from "vue";
|
||||
import { ElMessage, ElLoading } from "element-plus";
|
||||
import type { FormInstance, FormRules } from "element-plus";
|
||||
import { getCompanySeo, saveCompanySeo } from "@/api/sitesettings";
|
||||
|
||||
const seoFormRef = ref<FormInstance>();
|
||||
|
||||
const seoForm = reactive({
|
||||
seoTitle: "",
|
||||
seoKeywords: "",
|
||||
seoDescription: "",
|
||||
});
|
||||
|
||||
const seoRules: FormRules = {
|
||||
seoTitle: [{ required: true, message: "请输入SEO标题", trigger: "blur" }],
|
||||
};
|
||||
|
||||
const fetchSeoData = async () => {
|
||||
try {
|
||||
const res = await getCompanySeo();
|
||||
if (res.code === 200) {
|
||||
Object.assign(seoForm, res.data);
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error("获取SEO数据失败");
|
||||
}
|
||||
};
|
||||
|
||||
const saveSeoSettings = async () => {
|
||||
if (!seoFormRef.value) return;
|
||||
|
||||
await seoFormRef.value.validate(async (valid) => {
|
||||
if (valid) {
|
||||
const loading = ElLoading.service({ text: "正在保存..." });
|
||||
try {
|
||||
const res = await saveCompanySeo({
|
||||
seoTitle: seoForm.seoTitle,
|
||||
seoKeywords: seoForm.seoKeywords,
|
||||
seoDescription: seoForm.seoDescription,
|
||||
});
|
||||
|
||||
if (res.code === 200) {
|
||||
ElMessage.success("SEO设置保存成功");
|
||||
} else {
|
||||
ElMessage.error(res.msg);
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage.error("网络请求失败");
|
||||
} finally {
|
||||
loading.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const resetSeoForm = () => {
|
||||
if (!seoFormRef.value) return;
|
||||
seoFormRef.value.resetFields();
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
fetchSeoData();
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
seoForm,
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,98 @@
|
||||
<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="basic">
|
||||
<normalSettings
|
||||
ref="normalSettingsRef"
|
||||
v-if="activeTab === 'basic'"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="SEO设置" name="seo">
|
||||
<seoSettings ref="seoSettingsRef" v-if="activeTab === 'seo'" />
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="联系方式" name="contact">
|
||||
<contactSettings
|
||||
ref="contactSettingsRef"
|
||||
v-if="activeTab === 'contact'"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="登录验证" v-if="groupId === 1" name="loginVerification">
|
||||
<loginVerificationSettings
|
||||
ref="loginVerificationSettingsRef"
|
||||
v-if="activeTab === 'loginVerification'"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="法律声明&隐私条款" name="legalNotice">
|
||||
<legalNoticeSettings
|
||||
ref="legalNoticeSettingsRef"
|
||||
v-if="activeTab === 'legalNotice'"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="其他设置" name="other">
|
||||
<otherSettings ref="otherSettingsRef" v-if="activeTab === 'other'" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from "vue";
|
||||
import normalSettings from "./components/normalSettings.vue";
|
||||
import seoSettings from "./components/seoSettings.vue";
|
||||
import contactSettings from "./components/contactSettings.vue";
|
||||
import otherSettings from "./components/otherSettings.vue";
|
||||
import legalNoticeSettings from "./components/legalNotice.vue";
|
||||
import loginVerificationSettings from "./components/loginVerification.vue";
|
||||
import { useAuthStore } from '@/stores/auth';
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const groupId = (authStore.userInfo as any)?.group_id;
|
||||
const activeTab = ref("basic");
|
||||
</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>
|
||||
Reference in New Issue
Block a user