更新操作日志和登录日志的数据隔离
This commit is contained in:
@@ -46,7 +46,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-table :data="pagedRows" v-loading="loading" stripe>
|
<el-table :data="pagedRows" v-loading="loading" stripe>
|
||||||
<el-table-column prop="id" label="ID" width="70" align="center" />
|
<!--<el-table-column prop="id" label="ID" width="70" align="center" />-->
|
||||||
<el-table-column prop="position_code" label="职位编码" width="150" />
|
<el-table-column prop="position_code" label="职位编码" width="150" />
|
||||||
<el-table-column prop="position_name" label="职位名称" min-width="140" />
|
<el-table-column prop="position_name" label="职位名称" min-width="140" />
|
||||||
<el-table-column label="所属部门" min-width="150">
|
<el-table-column label="所属部门" min-width="150">
|
||||||
|
|||||||
@@ -1,301 +1,328 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-form
|
<el-form
|
||||||
ref="normalFormRef"
|
ref="normalFormRef"
|
||||||
:model="formData"
|
:model="formData"
|
||||||
:rules="normalRules"
|
:rules="normalRules"
|
||||||
label-width="120px"
|
label-width="120px"
|
||||||
style="max-width: 600px"
|
style="max-width: 600px"
|
||||||
>
|
>
|
||||||
<el-form-item label="站点名称" prop="sitename">
|
<el-form-item label="站点名称" prop="sitename">
|
||||||
<el-input v-model="sitename" placeholder="请输入站点名称" />
|
<el-input v-model="sitename" placeholder="请输入站点名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="站点Logo" prop="logo">
|
<el-form-item label="站点Logo" prop="logo">
|
||||||
<el-upload
|
<el-upload
|
||||||
class="logo-uploader"
|
class="logo-uploader"
|
||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
:auto-upload="false"
|
:auto-upload="false"
|
||||||
:on-change="handleLogoChange"
|
:on-change="handleLogoChange"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-if="logo"
|
v-if="logo"
|
||||||
:src="getPreviewUrl(logo)"
|
:src="getPreviewUrl(logo)"
|
||||||
class="logo-image"
|
class="logo-image"
|
||||||
/>
|
/>
|
||||||
<el-icon v-else class="logo-uploader-icon"><Plus /></el-icon>
|
<el-icon v-else class="logo-uploader-icon"><Plus /></el-icon>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="站点Logo-浅色" prop="logow">
|
<el-form-item label="站点Logo-浅色" prop="logow">
|
||||||
<el-upload
|
<el-upload
|
||||||
class="logo-uploader"
|
class="logo-uploader"
|
||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
:auto-upload="false"
|
:auto-upload="false"
|
||||||
:on-change="handleLogowChange"
|
:on-change="handleLogowChange"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-if="logow"
|
v-if="logow"
|
||||||
:src="getPreviewUrl(logow)"
|
:src="getPreviewUrl(logow)"
|
||||||
class="logo-image darkbg"
|
class="logo-image darkbg"
|
||||||
/>
|
/>
|
||||||
<el-icon v-else class="logo-uploader-icon"><Plus /></el-icon>
|
<el-icon v-else class="logo-uploader-icon"><Plus /></el-icon>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="站点图标" prop="ico">
|
<el-form-item label="站点图标" prop="ico">
|
||||||
<el-upload
|
<el-upload
|
||||||
class="logo-uploader"
|
class="logo-uploader"
|
||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
:auto-upload="false"
|
:auto-upload="false"
|
||||||
:on-change="handleIconChange"
|
:on-change="handleIconChange"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
v-if="ico"
|
v-if="ico"
|
||||||
:src="getPreviewUrl(ico)"
|
:src="getPreviewUrl(ico)"
|
||||||
class="logo-image"
|
class="logo-image"
|
||||||
/>
|
/>
|
||||||
<el-icon v-else class="logo-uploader-icon"><Plus /></el-icon>
|
<el-icon v-else class="logo-uploader-icon"><Plus /></el-icon>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
<div class="form-tip">请上传ico格式文件</div>
|
<div class="form-tip">请上传ico格式文件</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="企业名称" prop="companyname">
|
<el-form-item label="企业名称" prop="companyname">
|
||||||
<el-input v-model="companyname" placeholder="请输入企业名称" />
|
<el-input v-model="companyname" placeholder="请输入企业名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="企业介绍" prop="companyintroduction">
|
<el-form-item label="企业简称" prop="company_short_name">
|
||||||
<el-input v-model="companyintroduction" type="textarea" rows="5" placeholder="请输入企业介绍" />
|
<el-input v-model="companyShortName" placeholder="请输入企业简称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="站点简介" prop="description">
|
<el-form-item label="企业英文名称" prop="company_english_name">
|
||||||
<el-input v-model="description" placeholder="请输入站点简介" />
|
<el-input v-model="companyEnglishName" placeholder="请输入企业英文名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="版权信息" prop="copyright">
|
<el-form-item label="企业英文简称" prop="company_english_short_name">
|
||||||
<el-input v-model="copyright" placeholder="如:© 2026 公司名称" />
|
<el-input v-model="companyEnglishShortName" placeholder="请输入企业英文简称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="备案号 " prop="icp">
|
<el-form-item label="企业介绍" prop="companyintroduction">
|
||||||
<el-input v-model="icp" placeholder="如:苏ICP备20260000号" />
|
<el-input v-model="companyintroduction" type="textarea" rows="5" placeholder="请输入企业介绍" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item label="站点简介" prop="description">
|
||||||
<el-button type="primary" @click="handleSaveNormalInfos"
|
<el-input v-model="description" placeholder="请输入站点简介" />
|
||||||
>保存设置</el-button
|
</el-form-item>
|
||||||
>
|
<el-form-item label="版权信息" prop="copyright">
|
||||||
<el-button @click="resetnormalForm">重置</el-button>
|
<el-input v-model="copyright" placeholder="如:© 2026 公司名称" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
<el-form-item label="备案号 " prop="icp">
|
||||||
</template>
|
<el-input v-model="icp" placeholder="如:苏ICP备20260000号" />
|
||||||
|
</el-form-item>
|
||||||
<script setup lang="ts">
|
<el-form-item>
|
||||||
import { ref, onMounted } from "vue";
|
<el-button type="primary" @click="handleSaveNormalInfos"
|
||||||
import { ElMessage } from "element-plus";
|
>保存设置</el-button
|
||||||
import { Plus } from "@element-plus/icons-vue";
|
>
|
||||||
import type { FormInstance, FormRules, UploadFile } from "element-plus";
|
<el-button @click="resetnormalForm">重置</el-button>
|
||||||
import { getNormalInfos, saveNormalInfos } from "@/api/sitesettings";
|
</el-form-item>
|
||||||
import { uploadFile } from "@/api/file";
|
</el-form>
|
||||||
import { useAuthStore } from "@/stores/auth";
|
</template>
|
||||||
|
|
||||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
|
<script setup lang="ts">
|
||||||
const authStore = useAuthStore();
|
import { ref, onMounted } from "vue";
|
||||||
|
import { ElMessage } from "element-plus";
|
||||||
const normalFormRef = ref<FormInstance>();
|
import { Plus } from "@element-plus/icons-vue";
|
||||||
|
import type { FormInstance, FormRules, UploadFile } from "element-plus";
|
||||||
const sitename = ref("");
|
import { getNormalInfos, saveNormalInfos } from "@/api/sitesettings";
|
||||||
const companyname = ref("");
|
import { uploadFile } from "@/api/file";
|
||||||
const companyintroduction = ref("");
|
import { useAuthStore } from "@/stores/auth";
|
||||||
const logo = ref("");
|
|
||||||
const logow = ref("");
|
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
|
||||||
const description = ref("");
|
const authStore = useAuthStore();
|
||||||
const copyright = ref("");
|
|
||||||
const icp = ref("");
|
const normalFormRef = ref<FormInstance>();
|
||||||
const ico = ref("");
|
|
||||||
|
const sitename = ref("");
|
||||||
const formData = {
|
const companyname = ref("");
|
||||||
sitename,
|
const companyShortName = ref("");
|
||||||
companyname,
|
const companyEnglishName = ref("");
|
||||||
companyintroduction,
|
const companyEnglishShortName = ref("");
|
||||||
logo,
|
const companyintroduction = ref("");
|
||||||
logow,
|
const logo = ref("");
|
||||||
ico,
|
const logow = ref("");
|
||||||
description,
|
const description = ref("");
|
||||||
copyright,
|
const copyright = ref("");
|
||||||
icp,
|
const icp = ref("");
|
||||||
};
|
const ico = ref("");
|
||||||
|
|
||||||
const normalRules: FormRules = {
|
const formData = {
|
||||||
sitename: [{ required: true, message: "请输入站点名称", trigger: "blur" }],
|
sitename,
|
||||||
};
|
companyname,
|
||||||
|
companyShortName,
|
||||||
const getPreviewUrl = (url: string) => {
|
companyEnglishName,
|
||||||
const value = String(url || "").trim().replace(/\\/g, "/");
|
companyEnglishShortName,
|
||||||
if (!value) return "";
|
companyintroduction,
|
||||||
if (/^(https?:\/\/|\/\/|data:|blob:)/i.test(value)) {
|
logo,
|
||||||
return value;
|
logow,
|
||||||
}
|
ico,
|
||||||
|
description,
|
||||||
const base = String(API_BASE_URL || "").replace(/\/+$/, "");
|
copyright,
|
||||||
const path = value.startsWith("/") ? value : `/${value}`;
|
icp,
|
||||||
return `${base}${path}`;
|
};
|
||||||
};
|
|
||||||
|
const normalRules: FormRules = {
|
||||||
//调用基础数据
|
sitename: [{ required: true, message: "请输入站点名称", trigger: "blur" }],
|
||||||
const initNormalInfos = async () => {
|
};
|
||||||
const res = await getNormalInfos(authStore.user.tid);
|
|
||||||
if (res.code === 200 && res.data) {
|
const getPreviewUrl = (url: string) => {
|
||||||
const data = res.data;
|
const value = String(url || "").trim().replace(/\\/g, "/");
|
||||||
sitename.value = data.sitename || "";
|
if (!value) return "";
|
||||||
companyintroduction.value = data.companyintroduction || "";
|
if (/^(https?:\/\/|\/\/|data:|blob:)/i.test(value)) {
|
||||||
logo.value = data.logo || "";
|
return value;
|
||||||
logow.value = data.logow || "";
|
}
|
||||||
ico.value = data.ico || "";
|
|
||||||
description.value = data.description || "";
|
const base = String(API_BASE_URL || "").replace(/\/+$/, "");
|
||||||
copyright.value = data.copyright || "";
|
const path = value.startsWith("/") ? value : `/${value}`;
|
||||||
icp.value = data.icp || "";
|
return `${base}${path}`;
|
||||||
companyname.value = data.companyname || "";
|
};
|
||||||
}
|
|
||||||
};
|
//调用基础数据
|
||||||
|
const initNormalInfos = async () => {
|
||||||
const handleLogoChange = (file: UploadFile) => {
|
const res = await getNormalInfos(authStore.user.tid);
|
||||||
const uploadFormData = new FormData();
|
if (res.code === 200 && res.data) {
|
||||||
uploadFormData.append("file", file.raw);
|
const data = res.data;
|
||||||
uploadFormData.append("cate", "site");
|
sitename.value = data.sitename || "";
|
||||||
|
companyintroduction.value = data.companyintroduction || "";
|
||||||
uploadFile(uploadFormData).then((uploadRes) => {
|
logo.value = data.logo || "";
|
||||||
if (
|
logow.value = data.logow || "";
|
||||||
(uploadRes.code === 200 || uploadRes.code === 201) &&
|
ico.value = data.ico || "";
|
||||||
uploadRes.data &&
|
description.value = data.description || "";
|
||||||
uploadRes.data.url
|
copyright.value = data.copyright || "";
|
||||||
) {
|
icp.value = data.icp || "";
|
||||||
logo.value = uploadRes.data.url.replace(/\\/g, "/");
|
companyname.value = data.companyname || "";
|
||||||
} else {
|
companyShortName.value = data.company_short_name || "";
|
||||||
ElMessage.error(uploadRes.msg || "上传失败");
|
companyEnglishName.value = data.company_english_name || "";
|
||||||
}
|
companyEnglishShortName.value = data.company_english_short_name || "";
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLogowChange = (file: UploadFile) => {
|
const handleLogoChange = (file: UploadFile) => {
|
||||||
const uploadFormData = new FormData();
|
const uploadFormData = new FormData();
|
||||||
uploadFormData.append("file", file.raw);
|
uploadFormData.append("file", file.raw);
|
||||||
uploadFormData.append("cate", "site");
|
uploadFormData.append("cate", "site");
|
||||||
|
|
||||||
uploadFile(uploadFormData).then((uploadRes) => {
|
uploadFile(uploadFormData).then((uploadRes) => {
|
||||||
if (
|
if (
|
||||||
(uploadRes.code === 200 || uploadRes.code === 201) &&
|
(uploadRes.code === 200 || uploadRes.code === 201) &&
|
||||||
uploadRes.data &&
|
uploadRes.data &&
|
||||||
uploadRes.data.url
|
uploadRes.data.url
|
||||||
) {
|
) {
|
||||||
logow.value = uploadRes.data.url.replace(/\\/g, "/");
|
logo.value = uploadRes.data.url.replace(/\\/g, "/");
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error(uploadRes.msg || "上传失败");
|
ElMessage.error(uploadRes.msg || "上传失败");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSaveNormalInfos = async () => {
|
const handleLogowChange = (file: UploadFile) => {
|
||||||
if (!normalFormRef.value) return;
|
const uploadFormData = new FormData();
|
||||||
await normalFormRef.value.validate(async (valid) => {
|
uploadFormData.append("file", file.raw);
|
||||||
if (valid) {
|
uploadFormData.append("cate", "site");
|
||||||
const data = {
|
|
||||||
tid: authStore.user.tid,
|
uploadFile(uploadFormData).then((uploadRes) => {
|
||||||
sitename: sitename.value,
|
if (
|
||||||
companyintroduction: companyintroduction.value,
|
(uploadRes.code === 200 || uploadRes.code === 201) &&
|
||||||
logo: logo.value,
|
uploadRes.data &&
|
||||||
logow: logow.value,
|
uploadRes.data.url
|
||||||
ico: ico.value,
|
) {
|
||||||
description: description.value,
|
logow.value = uploadRes.data.url.replace(/\\/g, "/");
|
||||||
companyname: companyname.value,
|
} else {
|
||||||
copyright: copyright.value,
|
ElMessage.error(uploadRes.msg || "上传失败");
|
||||||
icp: icp.value,
|
}
|
||||||
};
|
});
|
||||||
const res = await saveNormalInfos(data);
|
};
|
||||||
if (res.code === 200) {
|
|
||||||
ElMessage.success("保存成功");
|
const handleSaveNormalInfos = async () => {
|
||||||
} else {
|
if (!normalFormRef.value) return;
|
||||||
ElMessage.error(res.msg || "保存失败");
|
await normalFormRef.value.validate(async (valid) => {
|
||||||
}
|
if (valid) {
|
||||||
}
|
const data = {
|
||||||
});
|
tid: authStore.user.tid,
|
||||||
};
|
sitename: sitename.value,
|
||||||
|
companyintroduction: companyintroduction.value,
|
||||||
const handleIconChange = (file: UploadFile) => {
|
logo: logo.value,
|
||||||
const uploadFormData = new FormData();
|
logow: logow.value,
|
||||||
uploadFormData.append("file", file.raw);
|
ico: ico.value,
|
||||||
uploadFormData.append("cate", "site");
|
description: description.value,
|
||||||
|
companyname: companyname.value,
|
||||||
uploadFile(uploadFormData).then((uploadRes) => {
|
company_short_name: companyShortName.value,
|
||||||
if ((uploadRes.code === 200 || uploadRes.code === 201) && uploadRes.data?.url) {
|
company_english_name: companyEnglishName.value,
|
||||||
ico.value = uploadRes.data.url.replace(/\\/g, "/");
|
company_english_short_name: companyEnglishShortName.value,
|
||||||
} else {
|
copyright: copyright.value,
|
||||||
ElMessage.error(uploadRes.msg || "上传失败");
|
icp: icp.value,
|
||||||
}
|
};
|
||||||
});
|
const res = await saveNormalInfos(data);
|
||||||
};
|
if (res.code === 200) {
|
||||||
|
ElMessage.success("保存成功");
|
||||||
const resetnormalForm = () => {
|
} else {
|
||||||
sitename.value = "";
|
ElMessage.error(res.msg || "保存失败");
|
||||||
companyname.value = "";
|
}
|
||||||
companyintroduction.value = "";
|
}
|
||||||
logo.value = "";
|
});
|
||||||
logow.value = "";
|
};
|
||||||
ico.value = "";
|
|
||||||
description.value = "";
|
const handleIconChange = (file: UploadFile) => {
|
||||||
copyright.value = "";
|
const uploadFormData = new FormData();
|
||||||
icp.value = "";
|
uploadFormData.append("file", file.raw);
|
||||||
};
|
uploadFormData.append("cate", "site");
|
||||||
|
|
||||||
defineExpose({
|
uploadFile(uploadFormData).then((uploadRes) => {
|
||||||
sitename,
|
if ((uploadRes.code === 200 || uploadRes.code === 201) && uploadRes.data?.url) {
|
||||||
companyname,
|
ico.value = uploadRes.data.url.replace(/\\/g, "/");
|
||||||
companyintroduction,
|
} else {
|
||||||
logo,
|
ElMessage.error(uploadRes.msg || "上传失败");
|
||||||
logow,
|
}
|
||||||
ico,
|
});
|
||||||
description,
|
};
|
||||||
copyright,
|
|
||||||
icp,
|
const resetnormalForm = () => {
|
||||||
});
|
sitename.value = "";
|
||||||
|
companyname.value = "";
|
||||||
// 初始化基础数据
|
companyShortName.value = "";
|
||||||
onMounted(() => {
|
companyEnglishName.value = "";
|
||||||
initNormalInfos();
|
companyEnglishShortName.value = "";
|
||||||
});
|
companyintroduction.value = "";
|
||||||
</script>
|
logo.value = "";
|
||||||
|
logow.value = "";
|
||||||
<style lang="less" scoped>
|
ico.value = "";
|
||||||
.darkbg {
|
description.value = "";
|
||||||
background-color: #efefef;
|
copyright.value = "";
|
||||||
}
|
icp.value = "";
|
||||||
|
};
|
||||||
.form-tip{
|
|
||||||
margin-left: 20px;
|
defineExpose({
|
||||||
color: #999;
|
sitename,
|
||||||
font-size: 12px;
|
companyname,
|
||||||
margin-top: 5px;
|
companyShortName,
|
||||||
}
|
companyEnglishName,
|
||||||
|
companyEnglishShortName,
|
||||||
.logo-uploader {
|
companyintroduction,
|
||||||
:deep(.el-upload) {
|
logo,
|
||||||
border: 1px dashed #d9d9d9;
|
logow,
|
||||||
border-radius: 6px;
|
ico,
|
||||||
cursor: pointer;
|
description,
|
||||||
position: relative;
|
copyright,
|
||||||
overflow: hidden;
|
icp,
|
||||||
transition: all 0.3s;
|
});
|
||||||
|
|
||||||
&:hover {
|
// 初始化基础数据
|
||||||
border-color: #3973ff;
|
onMounted(() => {
|
||||||
}
|
initNormalInfos();
|
||||||
}
|
});
|
||||||
|
</script>
|
||||||
.logo-uploader-icon {
|
|
||||||
font-size: 28px;
|
<style lang="less" scoped>
|
||||||
color: #8c939d;
|
.darkbg {
|
||||||
width: 100px;
|
background-color: #efefef;
|
||||||
height: 100px;
|
}
|
||||||
text-align: center;
|
|
||||||
display: flex;
|
.form-tip{
|
||||||
align-items: center;
|
margin-left: 20px;
|
||||||
justify-content: center;
|
color: #999;
|
||||||
}
|
font-size: 12px;
|
||||||
|
margin-top: 5px;
|
||||||
.logo-image {
|
}
|
||||||
width: 100px;
|
|
||||||
height: 100px;
|
.logo-uploader {
|
||||||
object-fit: contain;
|
:deep(.el-upload) {
|
||||||
display: block;
|
border: 1px dashed #d9d9d9;
|
||||||
}
|
border-radius: 6px;
|
||||||
}
|
cursor: pointer;
|
||||||
</style>
|
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>
|
||||||
|
|||||||
@@ -80,8 +80,8 @@
|
|||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
@selection-change="handleSelectionChange"
|
@selection-change="handleSelectionChange"
|
||||||
>
|
>
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<!--<el-table-column type="selection" width="55" align="center" />
|
||||||
<el-table-column prop="id" label="ID" width="60" align="center" />
|
<el-table-column prop="id" label="ID" width="60" align="center" />-->
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="user_name"
|
prop="user_name"
|
||||||
label="用户姓名"
|
label="用户姓名"
|
||||||
|
|||||||
@@ -67,8 +67,8 @@
|
|||||||
v-loading="loading"
|
v-loading="loading"
|
||||||
@selection-change="handleSelectionChange"
|
@selection-change="handleSelectionChange"
|
||||||
>
|
>
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<!--<el-table-column type="selection" width="55" align="center" />-->
|
||||||
<el-table-column prop="id" label="ID" width="60" align="center" />
|
<!--<el-table-column prop="id" label="ID" width="60" align="center" />-->
|
||||||
<el-table-column
|
<el-table-column
|
||||||
prop="user_name"
|
prop="user_name"
|
||||||
label="用户姓名"
|
label="用户姓名"
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"server/models"
|
"server/models"
|
||||||
|
"server/pkg/jwtutil"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/client/orm"
|
"github.com/beego/beego/v2/client/orm"
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
beego "github.com/beego/beego/v2/server/web"
|
||||||
@@ -17,6 +19,40 @@ type BackendErpContactController struct {
|
|||||||
beego.Controller
|
beego.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// contactClaims 从请求头解析登录态 JWT,返回后端用户 Claims
|
||||||
|
func (c *BackendErpContactController) contactClaims() (*jwtutil.Claims, error) {
|
||||||
|
auth := c.Ctx.Request.Header.Get("Authorization")
|
||||||
|
if auth == "" {
|
||||||
|
return nil, fmt.Errorf("未登录")
|
||||||
|
}
|
||||||
|
parts := strings.SplitN(auth, " ", 2)
|
||||||
|
if len(parts) != 2 || !strings.EqualFold(parts[0], "Bearer") {
|
||||||
|
return nil, fmt.Errorf("认证信息格式错误")
|
||||||
|
}
|
||||||
|
claims, err := jwtutil.ParseToken(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("无效的token")
|
||||||
|
}
|
||||||
|
if claims.UserType != "backend" {
|
||||||
|
return nil, fmt.Errorf("无权访问")
|
||||||
|
}
|
||||||
|
return claims, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// contactTenantID 获取当前请求的租户ID:优先使用登录态 JWT 中的租户,
|
||||||
|
// 仅当显式传入 tid 参数时才以参数为准(兼容管理端等显式指定场景)。
|
||||||
|
func (c *BackendErpContactController) contactTenantID() (uint64, error) {
|
||||||
|
claims, err := c.contactClaims()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
tid := uint64(claims.TenantId)
|
||||||
|
if v, e := c.GetInt64("tid"); e == nil && v > 0 {
|
||||||
|
tid = uint64(v)
|
||||||
|
}
|
||||||
|
return tid, nil
|
||||||
|
}
|
||||||
|
|
||||||
type erpContactDTO struct {
|
type erpContactDTO struct {
|
||||||
ID uint64 `json:"id"`
|
ID uint64 `json:"id"`
|
||||||
Tid uint64 `json:"tid"`
|
Tid uint64 `json:"tid"`
|
||||||
@@ -46,7 +82,11 @@ type erpContactDTO struct {
|
|||||||
// List 获取通讯录列表(支持分页、搜索、按组织筛选)
|
// List 获取通讯录列表(支持分页、搜索、按组织筛选)
|
||||||
// GET /backend/erp/contact/list
|
// GET /backend/erp/contact/list
|
||||||
func (c *BackendErpContactController) List() {
|
func (c *BackendErpContactController) List() {
|
||||||
tid, _ := c.GetInt64("tid")
|
tid, err := c.contactTenantID()
|
||||||
|
if err != nil {
|
||||||
|
c.contactJsonError(401, "未登录或无权访问")
|
||||||
|
return
|
||||||
|
}
|
||||||
page, _ := c.GetInt("page", 1)
|
page, _ := c.GetInt("page", 1)
|
||||||
pageSize, _ := c.GetInt("page_size", 20)
|
pageSize, _ := c.GetInt("page_size", 20)
|
||||||
keyword := strings.TrimSpace(c.GetString("keyword"))
|
keyword := strings.TrimSpace(c.GetString("keyword"))
|
||||||
@@ -62,10 +102,8 @@ func (c *BackendErpContactController) List() {
|
|||||||
|
|
||||||
qs := models.Orm.QueryTable(new(models.BackendErpContact)).
|
qs := models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||||
Filter("delete_time__isnull", true).
|
Filter("delete_time__isnull", true).
|
||||||
Exclude("status", 0)
|
Exclude("status", 0).
|
||||||
if tid > 0 {
|
Filter("tid", tid)
|
||||||
qs = qs.Filter("tid", tid)
|
|
||||||
}
|
|
||||||
if orgID > 0 {
|
if orgID > 0 {
|
||||||
qs = qs.Filter("org_id", orgID)
|
qs = qs.Filter("org_id", orgID)
|
||||||
}
|
}
|
||||||
@@ -398,17 +436,19 @@ func (c *BackendErpContactController) SyncAllContacts() {
|
|||||||
// GetContactOrgTree 获取通讯录组织树(带各部门联系人数量)
|
// GetContactOrgTree 获取通讯录组织树(带各部门联系人数量)
|
||||||
// GET /backend/erp/contact/orgTree
|
// GET /backend/erp/contact/orgTree
|
||||||
func (c *BackendErpContactController) GetContactOrgTree() {
|
func (c *BackendErpContactController) GetContactOrgTree() {
|
||||||
tid, _ := c.GetInt64("tid")
|
tid, err := c.contactTenantID()
|
||||||
|
if err != nil {
|
||||||
|
c.contactJsonError(401, "未登录或无权访问")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
qs := models.Orm.QueryTable(new(models.BackendOrganization)).
|
qs := models.Orm.QueryTable(new(models.BackendOrganization)).
|
||||||
Filter("delete_time__isnull", true).
|
Filter("delete_time__isnull", true).
|
||||||
Exclude("status", 0)
|
Exclude("status", 0).
|
||||||
if tid > 0 {
|
Filter("tid", tid)
|
||||||
qs = qs.Filter("tid", tid)
|
|
||||||
}
|
|
||||||
|
|
||||||
var orgs []models.BackendOrganization
|
var orgs []models.BackendOrganization
|
||||||
_, err := qs.OrderBy("sort", "id").All(&orgs)
|
_, err = qs.OrderBy("sort", "id").All(&orgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.contactJsonError(500, "查询组织架构失败: "+err.Error())
|
c.contactJsonError(500, "查询组织架构失败: "+err.Error())
|
||||||
return
|
return
|
||||||
@@ -418,10 +458,8 @@ func (c *BackendErpContactController) GetContactOrgTree() {
|
|||||||
cqs := models.Orm.QueryTable(new(models.BackendErpContact)).
|
cqs := models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||||
Filter("delete_time__isnull", true).
|
Filter("delete_time__isnull", true).
|
||||||
Exclude("status", 0).
|
Exclude("status", 0).
|
||||||
Filter("contact_type", 1)
|
Filter("contact_type", 1).
|
||||||
if tid > 0 {
|
Filter("tid", tid)
|
||||||
cqs = cqs.Filter("tid", tid)
|
|
||||||
}
|
|
||||||
|
|
||||||
type orgCount struct {
|
type orgCount struct {
|
||||||
OrgID uint64 `orm:"column(org_id)"`
|
OrgID uint64 `orm:"column(org_id)"`
|
||||||
@@ -437,6 +475,7 @@ func (c *BackendErpContactController) GetContactOrgTree() {
|
|||||||
for _, org := range orgs {
|
for _, org := range orgs {
|
||||||
cnt, _ := models.Orm.QueryTable(new(models.BackendErpContact)).
|
cnt, _ := models.Orm.QueryTable(new(models.BackendErpContact)).
|
||||||
Filter("org_id", org.ID).
|
Filter("org_id", org.ID).
|
||||||
|
Filter("tid", tid).
|
||||||
Filter("delete_time__isnull", true).
|
Filter("delete_time__isnull", true).
|
||||||
Exclude("status", 0).
|
Exclude("status", 0).
|
||||||
Filter("contact_type", 1).
|
Filter("contact_type", 1).
|
||||||
|
|||||||
@@ -48,10 +48,13 @@ func (c *BackendOperationLogController) jsonErr(httpStatus, bizCode int, msg str
|
|||||||
|
|
||||||
// List GET /backend/operationLogs?page=1&pageSize=20&keyword=&module=&action=&status=&startTime=&endTime=
|
// List GET /backend/operationLogs?page=1&pageSize=20&keyword=&module=&action=&status=&startTime=&endTime=
|
||||||
func (c *BackendOperationLogController) List() {
|
func (c *BackendOperationLogController) List() {
|
||||||
if _, err := c.backendClaims(); err != nil {
|
claims, err := c.backendClaims()
|
||||||
|
if err != nil {
|
||||||
c.jsonErr(401, 401, err.Error())
|
c.jsonErr(401, 401, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
uid := uint64(claims.UserID)
|
||||||
|
tid := uint64(claims.TenantId)
|
||||||
|
|
||||||
page, _ := c.GetInt("page", 1)
|
page, _ := c.GetInt("page", 1)
|
||||||
pageSize, _ := c.GetInt("pageSize", 20)
|
pageSize, _ := c.GetInt("pageSize", 20)
|
||||||
@@ -72,7 +75,10 @@ func (c *BackendOperationLogController) List() {
|
|||||||
startTimeStr := strings.TrimSpace(c.GetString("startTime"))
|
startTimeStr := strings.TrimSpace(c.GetString("startTime"))
|
||||||
endTimeStr := strings.TrimSpace(c.GetString("endTime"))
|
endTimeStr := strings.TrimSpace(c.GetString("endTime"))
|
||||||
|
|
||||||
qs := models.Orm.QueryTable(new(models.SystemOperationLog)).Filter("delete_time__isnull", true)
|
qs := models.Orm.QueryTable(new(models.SystemOperationLog)).
|
||||||
|
Filter("delete_time__isnull", true).
|
||||||
|
Filter("tid", tid).
|
||||||
|
Filter("user_id", uid)
|
||||||
|
|
||||||
// 条件拼装
|
// 条件拼装
|
||||||
cond := orm.NewCondition()
|
cond := orm.NewCondition()
|
||||||
@@ -174,10 +180,13 @@ func (c *BackendOperationLogController) List() {
|
|||||||
|
|
||||||
// Detail GET /backend/operationLogs/:id
|
// Detail GET /backend/operationLogs/:id
|
||||||
func (c *BackendOperationLogController) Detail() {
|
func (c *BackendOperationLogController) Detail() {
|
||||||
if _, err := c.backendClaims(); err != nil {
|
claims, err := c.backendClaims()
|
||||||
|
if err != nil {
|
||||||
c.jsonErr(401, 401, err.Error())
|
c.jsonErr(401, 401, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
uid := uint64(claims.UserID)
|
||||||
|
tid := uint64(claims.TenantId)
|
||||||
idStr := c.Ctx.Input.Param(":id")
|
idStr := c.Ctx.Input.Param(":id")
|
||||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||||
if err != nil || id == 0 {
|
if err != nil || id == 0 {
|
||||||
@@ -187,6 +196,8 @@ func (c *BackendOperationLogController) Detail() {
|
|||||||
var row models.SystemOperationLog
|
var row models.SystemOperationLog
|
||||||
err = models.Orm.QueryTable(new(models.SystemOperationLog)).
|
err = models.Orm.QueryTable(new(models.SystemOperationLog)).
|
||||||
Filter("id", id).
|
Filter("id", id).
|
||||||
|
Filter("tid", tid).
|
||||||
|
Filter("user_id", uid).
|
||||||
Filter("delete_time__isnull", true).
|
Filter("delete_time__isnull", true).
|
||||||
One(&row)
|
One(&row)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -219,10 +230,13 @@ func (c *BackendOperationLogController) Detail() {
|
|||||||
|
|
||||||
// Delete DELETE /backend/operationLogs/:id
|
// Delete DELETE /backend/operationLogs/:id
|
||||||
func (c *BackendOperationLogController) Delete() {
|
func (c *BackendOperationLogController) Delete() {
|
||||||
if _, err := c.backendClaims(); err != nil {
|
claims, err := c.backendClaims()
|
||||||
|
if err != nil {
|
||||||
c.jsonErr(401, 401, err.Error())
|
c.jsonErr(401, 401, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
uid := uint64(claims.UserID)
|
||||||
|
tid := uint64(claims.TenantId)
|
||||||
idStr := c.Ctx.Input.Param(":id")
|
idStr := c.Ctx.Input.Param(":id")
|
||||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||||
if err != nil || id == 0 {
|
if err != nil || id == 0 {
|
||||||
@@ -232,6 +246,8 @@ func (c *BackendOperationLogController) Delete() {
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
n, err := models.Orm.QueryTable(new(models.SystemOperationLog)).
|
n, err := models.Orm.QueryTable(new(models.SystemOperationLog)).
|
||||||
Filter("id", id).
|
Filter("id", id).
|
||||||
|
Filter("tid", tid).
|
||||||
|
Filter("user_id", uid).
|
||||||
Filter("delete_time__isnull", true).
|
Filter("delete_time__isnull", true).
|
||||||
Update(map[string]interface{}{"delete_time": now})
|
Update(map[string]interface{}{"delete_time": now})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -252,10 +268,13 @@ type backendBatchDeletePayload struct {
|
|||||||
|
|
||||||
// BatchDelete POST /backend/operationLogs/batchDelete
|
// BatchDelete POST /backend/operationLogs/batchDelete
|
||||||
func (c *BackendOperationLogController) BatchDelete() {
|
func (c *BackendOperationLogController) BatchDelete() {
|
||||||
if _, err := c.backendClaims(); err != nil {
|
claims, err := c.backendClaims()
|
||||||
|
if err != nil {
|
||||||
c.jsonErr(401, 401, err.Error())
|
c.jsonErr(401, 401, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
uid := uint64(claims.UserID)
|
||||||
|
tid := uint64(claims.TenantId)
|
||||||
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
raw, err := io.ReadAll(c.Ctx.Request.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.jsonErr(400, 400, "参数错误")
|
c.jsonErr(400, 400, "参数错误")
|
||||||
@@ -273,6 +292,8 @@ func (c *BackendOperationLogController) BatchDelete() {
|
|||||||
now := time.Now()
|
now := time.Now()
|
||||||
_, err = models.Orm.QueryTable(new(models.SystemOperationLog)).
|
_, err = models.Orm.QueryTable(new(models.SystemOperationLog)).
|
||||||
Filter("id__in", p.IDs).
|
Filter("id__in", p.IDs).
|
||||||
|
Filter("tid", tid).
|
||||||
|
Filter("user_id", uid).
|
||||||
Filter("delete_time__isnull", true).
|
Filter("delete_time__isnull", true).
|
||||||
Update(map[string]interface{}{"delete_time": now})
|
Update(map[string]interface{}{"delete_time": now})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -286,14 +307,19 @@ func (c *BackendOperationLogController) BatchDelete() {
|
|||||||
// Statistics GET /backend/operationLogs/statistics
|
// Statistics GET /backend/operationLogs/statistics
|
||||||
// 供前端筛选项:modules/actions
|
// 供前端筛选项:modules/actions
|
||||||
func (c *BackendOperationLogController) Statistics() {
|
func (c *BackendOperationLogController) Statistics() {
|
||||||
if _, err := c.backendClaims(); err != nil {
|
claims, err := c.backendClaims()
|
||||||
|
if err != nil {
|
||||||
c.jsonErr(401, 401, err.Error())
|
c.jsonErr(401, 401, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
uid := uint64(claims.UserID)
|
||||||
|
tid := uint64(claims.TenantId)
|
||||||
|
|
||||||
var moduleRows []models.SystemOperationLog
|
var moduleRows []models.SystemOperationLog
|
||||||
_, _ = models.Orm.QueryTable(new(models.SystemOperationLog)).
|
_, _ = models.Orm.QueryTable(new(models.SystemOperationLog)).
|
||||||
Filter("delete_time__isnull", true).
|
Filter("delete_time__isnull", true).
|
||||||
|
Filter("tid", tid).
|
||||||
|
Filter("user_id", uid).
|
||||||
Filter("module__isnull", false).
|
Filter("module__isnull", false).
|
||||||
Limit(1000).
|
Limit(1000).
|
||||||
All(&moduleRows, "Module")
|
All(&moduleRows, "Module")
|
||||||
@@ -312,6 +338,8 @@ func (c *BackendOperationLogController) Statistics() {
|
|||||||
var actionRows []models.SystemOperationLog
|
var actionRows []models.SystemOperationLog
|
||||||
_, _ = models.Orm.QueryTable(new(models.SystemOperationLog)).
|
_, _ = models.Orm.QueryTable(new(models.SystemOperationLog)).
|
||||||
Filter("delete_time__isnull", true).
|
Filter("delete_time__isnull", true).
|
||||||
|
Filter("tid", tid).
|
||||||
|
Filter("user_id", uid).
|
||||||
Filter("action__isnull", false).
|
Filter("action__isnull", false).
|
||||||
Limit(1000).
|
Limit(1000).
|
||||||
All(&actionRows, "Action")
|
All(&actionRows, "Action")
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
BIN
Binary file not shown.
Reference in New Issue
Block a user