更新若干bug

This commit is contained in:
李志强 2026-03-11 11:11:57 +08:00
parent 66e747dd8c
commit b904c5619d
7 changed files with 461 additions and 249 deletions

View File

@ -2,12 +2,14 @@ import request from "@/utils/request";
/**
* 获取基本信息
* @param {number} tid 租户ID
* @returns {Promise}
*/
export function getNormalInfos() {
export function getNormalInfos(tid) {
return request({
url: "/admin/normalInfos",
method: "get",
params: { tid }
});
}
@ -20,9 +22,7 @@ export function saveNormalInfos(data) {
return request({
url: "/admin/saveNormalInfos",
method: "post",
data: {
data: JSON.stringify(data)
},
data: data,
});
}
@ -52,12 +52,14 @@ export function saveVerifyInfos(data) {
/**
* 获取法律声明和隐私条款
* @param {number} tid 租户ID
* @returns {Promise}
*/
export function getLegalInfos() {
export function getLegalInfos(tid) {
return request({
url: "/admin/legalInfos",
method: "get",
params: { tid }
});
}
@ -70,8 +72,32 @@ export function saveLegalInfos(data) {
return request({
url: "/admin/saveLegalInfos",
method: "post",
data: {
data: JSON.stringify(data)
},
data: data,
});
}
/**
* 获取企业信息
* @param {number} tid 租户ID
* @returns {Promise}
*/
export function getCompanyInfos(tid) {
return request({
url: "/admin/companyInfos",
method: "get",
params: { tid }
});
}
/**
* 保存企业信息
* @param {Object} data 要保存的数据
* @returns {Promise}
*/
export function saveCompanyInfos(data) {
return request({
url: "/admin/saveCompanyInfos",
method: "post",
data: data,
});
}

View File

@ -20,10 +20,14 @@
</template>
<script setup lang="ts">
import { ref, reactive } from "vue";
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({
@ -37,12 +41,35 @@ 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((valid) => {
await contactFormRef.value.validate(async (valid) => {
if (valid) {
// TODO:
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 || "保存失败");
}
}
});
};
@ -57,4 +84,9 @@ const resetContactForm = () => {
defineExpose({
contactForm
});
//
onMounted(() => {
initCompanyInfos();
});
</script>

View File

@ -22,7 +22,7 @@
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="saveLegalInfos">保存设置</el-button>
<el-button type="primary" @click="handleSaveLegalInfos">保存设置</el-button>
<el-button @click="resetLegalNoticeForm">重置</el-button>
</el-form-item>
</el-form>
@ -34,7 +34,9 @@ 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("");
@ -64,12 +66,21 @@ const initLegalInfos = async () => {
}
};
const saveLegalInfos = async () => {
const handleSaveLegalInfos = async () => {
if (!legalNoticeFormRef.value) return;
await legalNoticeFormRef.value.validate((valid) => {
await legalNoticeFormRef.value.validate(async (valid) => {
if (valid) {
// TODO:
ElMessage.success("法律声明和隐私条款保存成功");
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 || "保存失败");
}
}
});
};

View File

@ -67,8 +67,10 @@ 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>();
@ -96,20 +98,16 @@ const normalRules: FormRules = {
//
const initNormalInfos = async () => {
const res = await getNormalInfos();
const res = await getNormalInfos(authStore.user.tid);
if (res.code === 200 && res.data) {
const data = res.data;
const dataMap: Record<string, string> = {};
data.forEach((item: any) => {
dataMap[item.label] = item.value;
});
sitename.value = dataMap["sitename"] || "";
logo.value = dataMap["logo"] || "";
logow.value = dataMap["logow"] || "";
description.value = dataMap["description"] || "";
copyright.value = dataMap["copyright"] || "";
icp.value = dataMap["icp"] || "";
companyname.value = dataMap["companyname"] || "";
sitename.value = data.sitename || "";
logo.value = data.logo || "";
logow.value = data.logow || "";
description.value = data.description || "";
copyright.value = data.copyright || "";
icp.value = data.icp || "";
companyname.value = data.companyname || "";
}
};
@ -153,15 +151,16 @@ const handleSaveNormalInfos = async () => {
if (!normalFormRef.value) return;
await normalFormRef.value.validate(async (valid) => {
if (valid) {
const data = [
{ label: "sitename", value: sitename.value },
{ label: "logo", value: logo.value },
{ label: "logow", value: logow.value },
{ label: "description", value: description.value },
{ label: "companyname", value: companyname.value },
{ label: "copyright", value: copyright.value },
{ label: "icp", value: icp.value },
];
const data = {
tid: authStore.user.tid,
sitename: sitename.value,
logo: logo.value,
logow: logow.value,
description: description.value,
companyname: companyname.value,
copyright: copyright.value,
icp: icp.value,
};
const res = await saveNormalInfos(data);
if (res.code === 200) {
ElMessage.success("保存成功");

View File

@ -9,7 +9,10 @@
<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'" />
<normalSettings
ref="normalSettingsRef"
v-if="activeTab === 'basic'"
/>
</el-tab-pane>
<el-tab-pane label="SEO设置" name="seo">
@ -17,15 +20,24 @@
</el-tab-pane>
<el-tab-pane label="联系方式" name="contact">
<contactSettings ref="contactSettingsRef" v-if="activeTab === 'contact'" />
<contactSettings
ref="contactSettingsRef"
v-if="activeTab === 'contact'"
/>
</el-tab-pane>
<el-tab-pane label="登录验证" name="loginVerification">
<loginVerificationSettings ref="loginVerificationSettingsRef" v-if="activeTab === 'loginVerification'" />
<loginVerificationSettings
ref="loginVerificationSettingsRef"
v-if="activeTab === 'loginVerification'"
/>
</el-tab-pane>
<el-tab-pane label="法律声明&隐私条款" name="legalNotice">
<legalNoticeSettings ref="legalNoticeSettingsRef" v-if="activeTab === 'legalNotice'" />
<legalNoticeSettings
ref="legalNoticeSettingsRef"
v-if="activeTab === 'legalNotice'"
/>
</el-tab-pane>
<el-tab-pane label="其他设置" name="other">

View File

@ -23,7 +23,11 @@
<el-table-column prop="main_domain" label="主域名" min-width="150" />
<el-table-column prop="full_domain" label="完整域名" min-width="200">
<template #default="scope">
<el-link type="primary" :href="'http://' + scope.row.full_domain" target="_blank">
<el-link
type="primary"
:href="'http://' + scope.row.full_domain"
target="_blank"
>
{{ scope.row.full_domain }}
</el-link>
</template>
@ -31,16 +35,31 @@
<el-table-column prop="status" label="状态" width="100" align="center">
<template #default="scope">
<el-tag v-if="scope.row.status === 0" type="warning">审核中</el-tag>
<el-tag v-else-if="scope.row.status === 1" type="success">已生效</el-tag>
<el-tag v-else-if="scope.row.status === 1" type="success"
>已生效</el-tag
>
<el-tag v-else type="danger">已禁用</el-tag>
</template>
</el-table-column>
<el-table-column prop="create_time" label="申请时间" width="180" />
<el-table-column label="操作" width="100" fixed="right" align="center">
<el-table-column label="操作" width="180" fixed="right" align="center">
<template #default="scope">
<el-button size="small" text type="primary" @click="handleCopy(scope.row.full_domain)">
<el-button
size="small"
text
type="primary"
@click="handleCopy(scope.row.full_domain)"
>
复制
</el-button>
<el-button
size="small"
text
type="danger"
@click="handleDelete(scope.row)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
@ -49,7 +68,11 @@
<el-dialog v-model="dialogVisible" title="申请二级域名" width="500px">
<el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
<el-form-item label="选择主域名" prop="main_domain">
<el-select v-model="form.main_domain" placeholder="请选择主域名" style="width: 100%;">
<el-select
v-model="form.main_domain"
placeholder="请选择主域名"
style="width: 100%"
>
<el-option
v-for="item in domainList"
:key="item.main_domain"
@ -60,104 +83,146 @@
</el-form-item>
<el-form-item label="二级前缀" prop="sub_domain">
<el-input v-model="form.sub_domain" placeholder="请输入二级域名前缀">
<template #append>{{ form.main_domain ? '.' + form.main_domain : '' }}</template>
<template #append>{{
form.main_domain ? "." + form.main_domain : ""
}}</template>
</el-input>
<div class="form-tip">只能包含字母数字和连字符不能以连字符开头或结尾</div>
<div class="form-tip">
只能包含字母数字和连字符不能以连字符开头或结尾
</div>
</el-form-item>
<el-form-item label="预览">
<div class="domain-preview">
{{ form.sub_domain ? form.sub_domain + '.' + (form.main_domain || 'example.com') : '请填写上方信息' }}
{{
form.sub_domain
? form.sub_domain + "." + (form.main_domain || "example.com")
: "请填写上方信息"
}}
</div>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleSubmit" :loading="submitLoading">提交申请</el-button>
<el-button type="primary" @click="handleSubmit" :loading="submitLoading"
>提交申请</el-button
>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { getMyDomains, applyTenantDomain, getEnabledDomains } from '@/api/domain'
import { useAuthStore } from '@/stores/auth'
import { ref, reactive, onMounted } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { Plus } from "@element-plus/icons-vue";
import {
getMyDomains,
applyTenantDomain,
getEnabledDomains,
deleteTenantDomain,
} from "@/api/domain";
import { useAuthStore } from "@/stores/auth";
const authStore = useAuthStore()
const loading = ref(false)
const submitLoading = ref(false)
const dialogVisible = ref(false)
const formRef = ref()
const authStore = useAuthStore();
const loading = ref(false);
const submitLoading = ref(false);
const dialogVisible = ref(false);
const formRef = ref();
const tableData = ref<any[]>([])
const domainList = ref<any[]>([])
const tableData = ref<any[]>([]);
const domainList = ref<any[]>([]);
const form = reactive({
main_domain: '',
sub_domain: ''
})
main_domain: "",
sub_domain: "",
});
const rules = {
main_domain: [
{ required: true, message: '请选择主域名', trigger: 'change' }
],
main_domain: [{ required: true, message: "请选择主域名", trigger: "change" }],
sub_domain: [
{ required: true, message: '请输入二级域名前缀', trigger: 'blur' },
{ pattern: /^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$/, message: '格式不正确', trigger: 'blur' }
]
}
{ required: true, message: "请输入二级域名前缀", trigger: "blur" },
{
pattern: /^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]$/,
message: "格式不正确",
trigger: "blur",
},
],
};
const fetchDomains = async () => {
loading.value = true
loading.value = true;
try {
//
const res = await getMyDomains({ tid: authStore.user.tid })
const res = await getMyDomains({ tid: authStore.user.tid });
if (res.code === 200) {
tableData.value = res.data || []
tableData.value = res.data || [];
}
//
const domainRes = await getEnabledDomains()
const domainRes = await getEnabledDomains();
if (domainRes.code === 200) {
domainList.value = domainRes.data || []
domainList.value = domainRes.data || [];
}
} finally {
loading.value = false
}
loading.value = false;
}
};
const handleSubmit = async () => {
await formRef.value.validate()
submitLoading.value = true
await formRef.value.validate();
submitLoading.value = true;
try {
const res = await applyTenantDomain({
tid: authStore.user.tid,
main_domain: form.main_domain,
sub_domain: form.sub_domain
})
sub_domain: form.sub_domain,
});
if (res.code === 200) {
ElMessage.success(res.msg)
dialogVisible.value = false
form.sub_domain = ''
fetchDomains()
ElMessage.success(res.msg);
dialogVisible.value = false;
form.sub_domain = "";
fetchDomains();
} else {
ElMessage.error(res.msg || '申请失败')
ElMessage.error(res.msg || "申请失败");
}
} finally {
submitLoading.value = false
}
submitLoading.value = false;
}
};
const handleCopy = (domain: string) => {
navigator.clipboard.writeText('http://' + domain)
ElMessage.success('链接已复制到剪贴板')
navigator.clipboard.writeText("http://" + domain);
ElMessage.success("链接已复制到剪贴板");
};
const handleDelete = async (row: any) => {
try {
await ElMessageBox.confirm(
`确定要删除域名 "${row.full_domain}" 吗?`,
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
);
const res = await deleteTenantDomain(row.id);
if (res.code === 200) {
ElMessage.success("删除成功");
fetchDomains();
} else {
ElMessage.error(res.msg || "删除失败");
}
} catch (error: any) {
if (error !== "cancel") {
console.error("删除失败:", error);
}
}
};
onMounted(() => {
fetchDomains()
})
fetchDomains();
});
</script>
<style lang="less" scoped>

View File

@ -22,20 +22,36 @@
<el-form :inline="true" :model="searchForm" class="search-form">
<el-form-item label="租户名称">
<el-input v-model="searchForm.tenant_name" placeholder="请输入租户名称" clearable
@keyup.enter="handleSearch" />
<el-input
v-model="searchForm.tenant_name"
placeholder="请输入租户名称"
clearable
@keyup.enter="handleSearch"
/>
</el-form-item>
<el-form-item label="租户编码">
<el-input v-model="searchForm.tenant_code" placeholder="请输入租户编码" clearable
@keyup.enter="handleSearch" />
<el-input
v-model="searchForm.tenant_code"
placeholder="请输入租户编码"
clearable
@keyup.enter="handleSearch"
/>
</el-form-item>
<el-form-item label="联系人">
<el-input v-model="searchForm.contact_person" placeholder="请输入联系人" clearable
@keyup.enter="handleSearch" />
<el-input
v-model="searchForm.contact_person"
placeholder="请输入联系人"
clearable
@keyup.enter="handleSearch"
/>
</el-form-item>
<el-form-item label="联系电话">
<el-input v-model="searchForm.contact_phone" placeholder="请输入联系电话" clearable
@keyup.enter="handleSearch" />
<el-input
v-model="searchForm.contact_phone"
placeholder="请输入联系电话"
clearable
@keyup.enter="handleSearch"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSearch">查询</el-button>
@ -46,12 +62,42 @@
<!-- 租户列表表格 -->
<el-table :data="tenants" style="width: 100%" v-loading="loading">
<el-table-column prop="id" label="ID" align="center" fixed="left" />
<el-table-column prop="tenant_name" label="租户名称" min-width="220" align="center" />
<el-table-column prop="tenant_code" label="租户编码" min-width="120" align="center" />
<el-table-column prop="contact_person" label="联系人" min-width="120" align="center" />
<el-table-column prop="contact_phone" label="联系电话" min-width="120" align="center" />
<el-table-column prop="contact_email" label="电子邮箱" min-width="180" align="center" />
<el-table-column prop="address" label="租户地址" min-width="300" align="center" />
<el-table-column
prop="tenant_name"
label="租户名称"
min-width="220"
align="center"
/>
<el-table-column
prop="tenant_code"
label="租户编码"
min-width="120"
align="center"
/>
<el-table-column
prop="contact_person"
label="联系人"
min-width="120"
align="center"
/>
<el-table-column
prop="contact_phone"
label="联系电话"
min-width="120"
align="center"
/>
<el-table-column
prop="contact_email"
label="电子邮箱"
min-width="180"
align="center"
/>
<el-table-column
prop="address"
label="租户地址"
min-width="300"
align="center"
/>
<el-table-column prop="status" label="租户状态" width="80" align="center">
<template #default="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">{{
@ -62,10 +108,22 @@
<el-table-column label="操作" width="280" align="center" fixed="right">
<template #default="scope">
<!-- <el-button size="small" @click="handleQualification(scope.row)">资质</el-button> -->
<el-button text size="small" @click="handleAddUser(scope.row)">增加用户</el-button>
<el-button text size="small" @click="handlePreview(scope.row)">查看</el-button>
<el-button text size="small" @click="editRef.open(scope.row.id)">编辑</el-button>
<el-button text size="small" type="danger" @click="handleDelete(scope.row)">删除</el-button>
<el-button text size="small" @click="handleAddUser(scope.row)"
>增加用户</el-button
>
<el-button text size="small" @click="handlePreview(scope.row)"
>查看</el-button
>
<el-button text size="small" @click="editRef.open(scope.row.id)"
>编辑</el-button
>
<el-button
text
size="small"
type="danger"
@click="handleDelete(scope.row)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
@ -77,20 +135,25 @@
<!-- 分页 -->
<div class="pagination-bar">
<el-pagination :current-page="page" :page-size="pageSize" :total="total" @current-change="handlePageChange"
layout="total, prev, pager, next" />
<el-pagination
:current-page="page"
:page-size="pageSize"
:total="total"
@current-change="handlePageChange"
layout="total, prev, pager, next"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { getTenantList, deleteTenant } from '@/api/tenant';
import { onMounted, ref, reactive } from 'vue';
import { useRouter } from 'vue-router';
import EditModal from './components/edit.vue';
import DetailDrawer from './components/detail.vue';
import Qualification from './components/qualification.vue';
import AddUser from './components/adduser.vue';
import { getTenantList, deleteTenant } from "@/api/tenant";
import { onMounted, ref, reactive } from "vue";
import { useRouter } from "vue-router";
import EditModal from "./components/edit.vue";
import DetailDrawer from "./components/detail.vue";
import Qualification from "./components/qualification.vue";
import AddUser from "./components/adduser.vue";
const total = ref(0);
const page = ref(1);
@ -106,16 +169,18 @@ const qualificationRef = ref();
//
const handleDelete = (row) => {
ElMessageBox.confirm('确定要删除该租户吗?', '提示', {
type: 'warning'
}).then(() => {
deleteTenant(row.id).then(res => {
ElMessageBox.confirm("确定要删除该租户吗?", "提示", {
type: "warning",
})
.then(() => {
deleteTenant(row.id).then((res) => {
if (res.code === 200) {
ElMessage.success('删除成功');
ElMessage.success("删除成功");
refresh();
}
});
}).catch(() => { });
})
.catch(() => {});
};
//
@ -141,10 +206,10 @@ const handlePageChange = (val: number) => {
//
const searchForm = reactive({
tenant_name: '',
tenant_code: '',
contact_person: '',
contact_phone: ''
tenant_name: "",
tenant_code: "",
contact_person: "",
contact_phone: "",
});
//
@ -155,10 +220,10 @@ const handleSearch = () => {
//
const resetSearch = () => {
searchForm.tenant_name = '';
searchForm.tenant_code = '';
searchForm.contact_person = '';
searchForm.contact_phone = '';
searchForm.tenant_name = "";
searchForm.tenant_code = "";
searchForm.contact_person = "";
searchForm.contact_phone = "";
handleSearch();
};
@ -170,15 +235,17 @@ const refresh = () => {
const queryParams = {
page: page.value,
pageSize: pageSize.value,
...searchForm
...searchForm,
};
getTenantList(queryParams).then(res => {
getTenantList(queryParams)
.then((res) => {
if (res.code === 200) {
tenants.value = res.data.list;
total.value = res.data.total;
}
}).finally(() => {
})
.finally(() => {
loading.value = false;
});
};