知识库增加租户隔离
This commit is contained in:
parent
b00463cb14
commit
9c67793fc3
@ -8,6 +8,14 @@ export function getAllMenus() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取租户菜单(根据角色权限)
|
||||||
|
export function getTenantMenus(roleId) {
|
||||||
|
return request({
|
||||||
|
url: `/api/menus/tenant/${roleId}`,
|
||||||
|
method: "get",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 更新菜单状态
|
// 更新菜单状态
|
||||||
export function updateMenuStatus(menuId, status) {
|
export function updateMenuStatus(menuId, status) {
|
||||||
return request({
|
return request({
|
||||||
|
|||||||
@ -34,7 +34,7 @@
|
|||||||
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
import { ref, computed, onMounted, onUnmounted } from 'vue';
|
||||||
import { useRouter, useRoute } from 'vue-router';
|
import { useRouter, useRoute } from 'vue-router';
|
||||||
import { useAllDataStore } from '@/stores';
|
import { useAllDataStore } from '@/stores';
|
||||||
import { getAllMenus } from '@/api/menu';
|
import { getAllMenus, getTenantMenus } from '@/api/menu';
|
||||||
import MenuTreeItem from './MenuTreeItem.vue';
|
import MenuTreeItem from './MenuTreeItem.vue';
|
||||||
|
|
||||||
const emit = defineEmits(['menu-click']);
|
const emit = defineEmits(['menu-click']);
|
||||||
@ -196,8 +196,20 @@ const transformMenuData = (menus) => {
|
|||||||
const fetchMenus = async () => {
|
const fetchMenus = async () => {
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
try {
|
try {
|
||||||
// 直接从接口获取菜单数据,不使用缓存
|
// 获取用户信息,判断登录类型
|
||||||
const res = await getAllMenus();
|
const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}');
|
||||||
|
const loginType = userInfo.type; // "user" 或 "employee"
|
||||||
|
const roleId = userInfo.role; // 角色ID
|
||||||
|
|
||||||
|
let res;
|
||||||
|
if (loginType === "employee" && roleId) {
|
||||||
|
// 员工登录,使用getTenantMenus接口
|
||||||
|
res = await getTenantMenus(roleId);
|
||||||
|
} else {
|
||||||
|
// 用户登录,使用getAllMenus接口
|
||||||
|
res = await getAllMenus();
|
||||||
|
}
|
||||||
|
|
||||||
if (res && res.success && res.data) {
|
if (res && res.success && res.data) {
|
||||||
const menuData = res.data;
|
const menuData = res.data;
|
||||||
// 转换并排序菜单数据
|
// 转换并排序菜单数据
|
||||||
|
|||||||
@ -62,7 +62,7 @@ import { useRouter, useRoute } from "vue-router";
|
|||||||
import { useAllDataStore } from "@/stores";
|
import { useAllDataStore } from "@/stores";
|
||||||
import { useAuthStore } from "@/stores/auth";
|
import { useAuthStore } from "@/stores/auth";
|
||||||
import { User, SwitchButton, Sunny, Moon, Refresh } from '@element-plus/icons-vue';
|
import { User, SwitchButton, Sunny, Moon, Refresh } from '@element-plus/icons-vue';
|
||||||
import { getAllMenus } from '@/api/menu';
|
import { getAllMenus, getTenantMenus } from '@/api/menu';
|
||||||
import { ElMessage } from 'element-plus';
|
import { ElMessage } from 'element-plus';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -111,7 +111,20 @@ function saveMenuToCache(menus: Menu[]) {
|
|||||||
// 从API加载菜单
|
// 从API加载菜单
|
||||||
async function loadMenuFromAPI(updateCache = true) {
|
async function loadMenuFromAPI(updateCache = true) {
|
||||||
try {
|
try {
|
||||||
const res = await getAllMenus();
|
// 获取用户信息,判断登录类型
|
||||||
|
const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}');
|
||||||
|
const loginType = userInfo.type; // "user" 或 "employee"
|
||||||
|
const roleId = userInfo.role; // 角色ID
|
||||||
|
|
||||||
|
let res;
|
||||||
|
if (loginType === "employee" && roleId) {
|
||||||
|
// 员工登录,使用getTenantMenus接口
|
||||||
|
res = await getTenantMenus(roleId);
|
||||||
|
} else {
|
||||||
|
// 用户登录,使用getAllMenus接口
|
||||||
|
res = await getAllMenus();
|
||||||
|
}
|
||||||
|
|
||||||
const menus = res.data || [];
|
const menus = res.data || [];
|
||||||
if (updateCache && menus.length > 0) {
|
if (updateCache && menus.length > 0) {
|
||||||
saveMenuToCache(menus);
|
saveMenuToCache(menus);
|
||||||
|
|||||||
@ -71,9 +71,22 @@ export async function loadAndAddDynamicRoutes() {
|
|||||||
// 创建加载 Promise
|
// 创建加载 Promise
|
||||||
routesLoadingPromise = (async () => {
|
routesLoadingPromise = (async () => {
|
||||||
try {
|
try {
|
||||||
// 直接从 API 获取菜单数据
|
// 获取用户信息,判断登录类型
|
||||||
const { getAllMenus } = await import("@/api/menu");
|
const userInfo = JSON.parse(localStorage.getItem('userInfo') || '{}');
|
||||||
const res = await getAllMenus();
|
const loginType = userInfo.type; // "user" 或 "employee"
|
||||||
|
const roleId = userInfo.role; // 角色ID
|
||||||
|
|
||||||
|
// 根据登录类型选择不同的菜单接口
|
||||||
|
const { getAllMenus, getTenantMenus } = await import("@/api/menu");
|
||||||
|
let res;
|
||||||
|
|
||||||
|
if (loginType === "employee" && roleId) {
|
||||||
|
// 员工登录,使用getTenantMenus接口
|
||||||
|
res = await getTenantMenus(roleId);
|
||||||
|
} else {
|
||||||
|
// 用户登录,使用getAllMenus接口
|
||||||
|
res = await getAllMenus();
|
||||||
|
}
|
||||||
|
|
||||||
if (res && res.success && res.data) {
|
if (res && res.success && res.data) {
|
||||||
// 添加动态路由
|
// 添加动态路由
|
||||||
|
|||||||
@ -27,10 +27,6 @@
|
|||||||
<h3 class="info-title">基本信息</h3>
|
<h3 class="info-title">基本信息</h3>
|
||||||
<el-divider />
|
<el-divider />
|
||||||
<div class="info-content">
|
<div class="info-content">
|
||||||
<div class="info-item">
|
|
||||||
<span class="info-label">标题:</span>
|
|
||||||
<span class="info-value">{{ formData.title }}</span>
|
|
||||||
</div>
|
|
||||||
<div class="info-item">
|
<div class="info-item">
|
||||||
<span class="info-label">分类:</span>
|
<span class="info-label">分类:</span>
|
||||||
<el-tag size="small" type="info">{{ formData.category }}</el-tag>
|
<el-tag size="small" type="info">{{ formData.category }}</el-tag>
|
||||||
@ -190,7 +186,6 @@ function handleDelete() {
|
|||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.knowledge-detail {
|
.knowledge-detail {
|
||||||
padding: 24px;
|
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
background-color: var(--el-bg-color-page);
|
background-color: var(--el-bg-color-page);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -519,7 +519,6 @@ onMounted(() => {
|
|||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
.knowledge-home {
|
.knowledge-home {
|
||||||
padding: 24px;
|
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
background-color: var(--el-bg-color-page);
|
background-color: var(--el-bg-color-page);
|
||||||
}
|
}
|
||||||
@ -806,7 +805,6 @@ onMounted(() => {
|
|||||||
// 响应式
|
// 响应式
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.knowledge-home {
|
.knowledge-home {
|
||||||
padding: 16px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-section {
|
.search-section {
|
||||||
|
|||||||
@ -41,6 +41,11 @@
|
|||||||
align="center"
|
align="center"
|
||||||
min-width="200"
|
min-width="200"
|
||||||
/>
|
/>
|
||||||
|
<el-table-column prop="role" label="角色" width="150" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ scope.row.roleName || '未分配' }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="department" label="部门" width="150" align="center">
|
<el-table-column prop="department" label="部门" width="150" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span>{{ scope.row.departmentName || '未分配' }}</span>
|
<span>{{ scope.row.departmentName || '未分配' }}</span>
|
||||||
@ -160,6 +165,27 @@
|
|||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="角色">
|
||||||
|
<el-select
|
||||||
|
v-model="form.role"
|
||||||
|
placeholder="请选择角色"
|
||||||
|
style="width: 100%"
|
||||||
|
:loading="loadingRoles"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="role in roleList"
|
||||||
|
:key="role.roleId"
|
||||||
|
:label="role.roleName"
|
||||||
|
:value="role.roleId"
|
||||||
|
>
|
||||||
|
<span>{{ role.roleName }}</span>
|
||||||
|
<span style="color: #8492a6; font-size: 13px; margin-left: 8px;">
|
||||||
|
({{ role.roleCode }})
|
||||||
|
</span>
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="开户行">
|
<el-form-item label="开户行">
|
||||||
<el-input v-model="form.bank_name" placeholder="请输入工资卡开户行" />
|
<el-input v-model="form.bank_name" placeholder="请输入工资卡开户行" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -231,6 +257,7 @@ import {
|
|||||||
} from "@/api/employee";
|
} from "@/api/employee";
|
||||||
import { getTenantDepartments, getDepartmentInfo } from "@/api/department";
|
import { getTenantDepartments, getDepartmentInfo } from "@/api/department";
|
||||||
import { getTenantPositions, getPositionsByDepartment, getPositionInfo } from "@/api/position";
|
import { getTenantPositions, getPositionsByDepartment, getPositionInfo } from "@/api/position";
|
||||||
|
import { getRoleByTenantId } from "@/api/role";
|
||||||
import { useAuthStore } from "@/stores/auth";
|
import { useAuthStore } from "@/stores/auth";
|
||||||
|
|
||||||
interface Employee {
|
interface Employee {
|
||||||
@ -241,6 +268,8 @@ interface Employee {
|
|||||||
email: string;
|
email: string;
|
||||||
department: string;
|
department: string;
|
||||||
position: string;
|
position: string;
|
||||||
|
role: number;
|
||||||
|
roleName?: string;
|
||||||
status: number;
|
status: number;
|
||||||
createTime: string;
|
createTime: string;
|
||||||
tenant_id: number;
|
tenant_id: number;
|
||||||
@ -258,6 +287,8 @@ const departmentTree = ref<any[]>([]);
|
|||||||
const loadingDepartments = ref(false);
|
const loadingDepartments = ref(false);
|
||||||
const positionList = ref<any[]>([]);
|
const positionList = ref<any[]>([]);
|
||||||
const loadingPositions = ref(false);
|
const loadingPositions = ref(false);
|
||||||
|
const roleList = ref<any[]>([]);
|
||||||
|
const loadingRoles = ref(false);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
// 获取当前登录用户的租户ID
|
// 获取当前登录用户的租户ID
|
||||||
@ -271,7 +302,7 @@ const getCurrentTenantId = () => {
|
|||||||
const user = JSON.parse(userInfo);
|
const user = JSON.parse(userInfo);
|
||||||
return user.tenant_id || user.tenantId || 0;
|
return user.tenant_id || user.tenantId || 0;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed to parse user info:', e);
|
console.error('解析用户信息失败:', e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -311,6 +342,14 @@ const fetchEmployees = async () => {
|
|||||||
positionName = posInfo ? posInfo.name : '';
|
positionName = posInfo ? posInfo.name : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查找角色名称
|
||||||
|
let roleName = '';
|
||||||
|
const roleId = item.role || null;
|
||||||
|
if (roleId) {
|
||||||
|
const roleInfo = roleList.value.find(r => r.roleId === roleId);
|
||||||
|
roleName = roleInfo ? roleInfo.roleName : '';
|
||||||
|
}
|
||||||
|
|
||||||
// 处理入职时间
|
// 处理入职时间
|
||||||
const createTime = item.create_time || item.createTime || null;
|
const createTime = item.create_time || item.createTime || null;
|
||||||
|
|
||||||
@ -324,6 +363,8 @@ const fetchEmployees = async () => {
|
|||||||
departmentName: departmentName,
|
departmentName: departmentName,
|
||||||
position_id: positionId,
|
position_id: positionId,
|
||||||
positionName: positionName,
|
positionName: positionName,
|
||||||
|
role: roleId,
|
||||||
|
roleName: roleName,
|
||||||
bankName: item.bank_name || item.bankName || '',
|
bankName: item.bank_name || item.bankName || '',
|
||||||
bankAccount: item.bank_account || item.bankAccount || '',
|
bankAccount: item.bank_account || item.bankAccount || '',
|
||||||
status: item.status || 1,
|
status: item.status || 1,
|
||||||
@ -515,10 +556,36 @@ const handleDepartmentChange = (departmentId: number | null) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 获取角色列表
|
||||||
|
const fetchRoles = async () => {
|
||||||
|
loadingRoles.value = true;
|
||||||
|
try {
|
||||||
|
const tenantId = getCurrentTenantId();
|
||||||
|
const res = await getRoleByTenantId(tenantId);
|
||||||
|
|
||||||
|
// 兼容接口返回的数据结构
|
||||||
|
if (res?.data && Array.isArray(res.data)) {
|
||||||
|
roleList.value = res.data;
|
||||||
|
} else if (res?.data?.data && Array.isArray(res.data.data)) {
|
||||||
|
roleList.value = res.data.data;
|
||||||
|
} else if (Array.isArray(res)) {
|
||||||
|
roleList.value = res;
|
||||||
|
} else {
|
||||||
|
roleList.value = [];
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('获取角色列表失败:', error);
|
||||||
|
roleList.value = [];
|
||||||
|
} finally {
|
||||||
|
loadingRoles.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
fetchDepartments(),
|
fetchDepartments(),
|
||||||
fetchPositions(),
|
fetchPositions(),
|
||||||
|
fetchRoles(),
|
||||||
]);
|
]);
|
||||||
fetchEmployees();
|
fetchEmployees();
|
||||||
});
|
});
|
||||||
@ -540,6 +607,7 @@ const form = ref<any>({
|
|||||||
email: "",
|
email: "",
|
||||||
department_id: null,
|
department_id: null,
|
||||||
position_id: null,
|
position_id: null,
|
||||||
|
role: null,
|
||||||
bank_name: "",
|
bank_name: "",
|
||||||
bank_account: "",
|
bank_account: "",
|
||||||
status: 1,
|
status: 1,
|
||||||
@ -592,6 +660,7 @@ const handleAddEmployee = () => {
|
|||||||
email: "",
|
email: "",
|
||||||
department_id: null,
|
department_id: null,
|
||||||
position_id: null,
|
position_id: null,
|
||||||
|
role: null,
|
||||||
bank_name: "",
|
bank_name: "",
|
||||||
bank_account: "",
|
bank_account: "",
|
||||||
status: 1,
|
status: 1,
|
||||||
@ -629,6 +698,7 @@ const handleEdit = async (employee: Employee) => {
|
|||||||
position_id: data.position_id ? Number(data.position_id) : null,
|
position_id: data.position_id ? Number(data.position_id) : null,
|
||||||
bank_name: data.bank_name || data.bankName || '',
|
bank_name: data.bank_name || data.bankName || '',
|
||||||
bank_account: data.bank_account || data.bankAccount || '',
|
bank_account: data.bank_account || data.bankAccount || '',
|
||||||
|
role: data.role || null,
|
||||||
status: data.status || 1,
|
status: data.status || 1,
|
||||||
tenant_id: data.tenant_id || tenantId,
|
tenant_id: data.tenant_id || tenantId,
|
||||||
};
|
};
|
||||||
@ -799,6 +869,7 @@ const submitForm = async () => {
|
|||||||
email: form.value.email,
|
email: form.value.email,
|
||||||
department_id: form.value.department_id || 0,
|
department_id: form.value.department_id || 0,
|
||||||
position_id: form.value.position_id || 0,
|
position_id: form.value.position_id || 0,
|
||||||
|
role: form.value.role || 0,
|
||||||
bank_name: form.value.bank_name || '',
|
bank_name: form.value.bank_name || '',
|
||||||
bank_account: form.value.bank_account || '',
|
bank_account: form.value.bank_account || '',
|
||||||
status: form.value.status,
|
status: form.value.status,
|
||||||
@ -821,22 +892,21 @@ const submitForm = async () => {
|
|||||||
fetchEmployees();
|
fetchEmployees();
|
||||||
} else {
|
} else {
|
||||||
// 构建提交数据
|
// 构建提交数据
|
||||||
|
const tenantId = getCurrentTenantId();
|
||||||
const submitData: any = {
|
const submitData: any = {
|
||||||
|
tenant_id: tenantId || form.value.tenant_id || 0,
|
||||||
employee_no: form.value.employeeNo,
|
employee_no: form.value.employeeNo,
|
||||||
name: form.value.name,
|
name: form.value.name,
|
||||||
phone: form.value.phone,
|
phone: form.value.phone || '',
|
||||||
email: form.value.email,
|
email: form.value.email || '',
|
||||||
department_id: form.value.department_id || 0,
|
department_id: form.value.department_id || 0,
|
||||||
position_id: form.value.position_id || 0,
|
position_id: form.value.position_id || 0,
|
||||||
|
role: form.value.role || 0,
|
||||||
bank_name: form.value.bank_name || '',
|
bank_name: form.value.bank_name || '',
|
||||||
bank_account: form.value.bank_account || '',
|
bank_account: form.value.bank_account || '',
|
||||||
status: form.value.status,
|
status: form.value.status || 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (form.value.tenant_id) {
|
|
||||||
submitData.tenant_id = form.value.tenant_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
await addEmployee(submitData);
|
await addEmployee(submitData);
|
||||||
ElMessage.success({
|
ElMessage.success({
|
||||||
message: "添加成功",
|
message: "添加成功",
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { ref, onMounted } from "vue";
|
|||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { useAuthStore } from "@/stores/auth";
|
import { useAuthStore } from "@/stores/auth";
|
||||||
import { login } from "@/api/login";
|
import { login } from "@/api/login";
|
||||||
import { getAllMenus } from "@/api/menu";
|
import { getAllMenus, getTenantMenus } from "@/api/menu";
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
@ -77,7 +77,20 @@ const handleLogin = async () => {
|
|||||||
|
|
||||||
// 登录成功后缓存菜单
|
// 登录成功后缓存菜单
|
||||||
try {
|
try {
|
||||||
const menuRes = await getAllMenus();
|
const userInfo = res.data.user || {};
|
||||||
|
const loginType = userInfo.type; // "user" 或 "employee"
|
||||||
|
const roleId = userInfo.role; // 角色ID
|
||||||
|
|
||||||
|
let menuRes;
|
||||||
|
// 判断是租户登录(员工)还是用户登录
|
||||||
|
if (loginType === "employee" && roleId) {
|
||||||
|
// 员工登录,使用getTenantMenus接口,根据角色权限过滤菜单
|
||||||
|
menuRes = await getTenantMenus(roleId);
|
||||||
|
} else {
|
||||||
|
// 用户登录,使用getAllMenus接口(获取所有菜单)
|
||||||
|
menuRes = await getAllMenus();
|
||||||
|
}
|
||||||
|
|
||||||
if (menuRes && menuRes.data && menuRes.data.length > 0) {
|
if (menuRes && menuRes.data && menuRes.data.length > 0) {
|
||||||
localStorage.setItem('menu_cache', JSON.stringify(menuRes.data));
|
localStorage.setItem('menu_cache', JSON.stringify(menuRes.data));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -232,6 +232,8 @@ import {
|
|||||||
changePassword,
|
changePassword,
|
||||||
} from "@/api/user";
|
} from "@/api/user";
|
||||||
import { getRoleByTenantId } from "@/api/role";
|
import { getRoleByTenantId } from "@/api/role";
|
||||||
|
import { getTenantDepartments } from "@/api/department";
|
||||||
|
import { getTenantPositions, getPositionsByDepartment } from "@/api/position";
|
||||||
import { useAuthStore } from "@/stores/auth";
|
import { useAuthStore } from "@/stores/auth";
|
||||||
|
|
||||||
interface User {
|
interface User {
|
||||||
|
|||||||
@ -91,6 +91,7 @@ func (c *AuthController) Login() {
|
|||||||
"avatar": user.Avatar,
|
"avatar": user.Avatar,
|
||||||
"nickname": user.Nickname,
|
"nickname": user.Nickname,
|
||||||
"tenant_id": user.TenantId,
|
"tenant_id": user.TenantId,
|
||||||
|
"role": user.Role, // 角色ID
|
||||||
"type": "user", // 标识是用户登录
|
"type": "user", // 标识是用户登录
|
||||||
}
|
}
|
||||||
} else if employee != nil {
|
} else if employee != nil {
|
||||||
@ -107,6 +108,7 @@ func (c *AuthController) Login() {
|
|||||||
"tenant_id": employee.TenantId,
|
"tenant_id": employee.TenantId,
|
||||||
"department_id": employee.DepartmentId,
|
"department_id": employee.DepartmentId,
|
||||||
"position_id": employee.PositionId,
|
"position_id": employee.PositionId,
|
||||||
|
"role": employee.Role, // 角色ID
|
||||||
"type": "employee", // 标识是员工登录
|
"type": "employee", // 标识是员工登录
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -69,10 +69,13 @@ func (c *EmployeeController) GetTenantEmployees() {
|
|||||||
"email": emp.Email,
|
"email": emp.Email,
|
||||||
"department_id": emp.DepartmentId,
|
"department_id": emp.DepartmentId,
|
||||||
"position_id": emp.PositionId,
|
"position_id": emp.PositionId,
|
||||||
|
"role": emp.Role,
|
||||||
"bank_name": emp.BankName,
|
"bank_name": emp.BankName,
|
||||||
"bank_account": emp.BankAccount,
|
"bank_account": emp.BankAccount,
|
||||||
"status": emp.Status,
|
"status": emp.Status,
|
||||||
"create_time": emp.CreateTime,
|
"create_time": emp.CreateTime,
|
||||||
|
"last_login_time": emp.LastLoginTime,
|
||||||
|
"last_login_ip": emp.LastLoginIp,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,10 +124,13 @@ func (c *EmployeeController) GetEmployeeInfo() {
|
|||||||
"email": employee.Email,
|
"email": employee.Email,
|
||||||
"department_id": employee.DepartmentId,
|
"department_id": employee.DepartmentId,
|
||||||
"position_id": employee.PositionId,
|
"position_id": employee.PositionId,
|
||||||
|
"role": employee.Role,
|
||||||
"bank_name": employee.BankName,
|
"bank_name": employee.BankName,
|
||||||
"bank_account": employee.BankAccount,
|
"bank_account": employee.BankAccount,
|
||||||
"status": employee.Status,
|
"status": employee.Status,
|
||||||
"create_time": employee.CreateTime,
|
"create_time": employee.CreateTime,
|
||||||
|
"last_login_time": employee.LastLoginTime,
|
||||||
|
"last_login_ip": employee.LastLoginIp,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
@ -141,9 +147,10 @@ func (c *EmployeeController) AddEmployee() {
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
DepartmentId int `json:"department_id"`
|
DepartmentId int `json:"department_id"`
|
||||||
PositionId int `json:"position_id"`
|
PositionId int `json:"position_id"`
|
||||||
|
Role int `json:"role"`
|
||||||
BankName string `json:"bank_name"`
|
BankName string `json:"bank_name"`
|
||||||
BankAccount string `json:"bank_account"`
|
BankAccount string `json:"bank_account"`
|
||||||
Status int8 `json:"status"`
|
Status int `json:"status"` // 使用int,前端传递number会自动转换
|
||||||
}
|
}
|
||||||
|
|
||||||
err := json.Unmarshal(c.Ctx.Input.RequestBody, &employeeData)
|
err := json.Unmarshal(c.Ctx.Input.RequestBody, &employeeData)
|
||||||
@ -165,16 +172,25 @@ func (c *EmployeeController) AddEmployee() {
|
|||||||
Email: employeeData.Email,
|
Email: employeeData.Email,
|
||||||
DepartmentId: employeeData.DepartmentId,
|
DepartmentId: employeeData.DepartmentId,
|
||||||
PositionId: employeeData.PositionId,
|
PositionId: employeeData.PositionId,
|
||||||
|
Role: employeeData.Role,
|
||||||
BankName: employeeData.BankName,
|
BankName: employeeData.BankName,
|
||||||
BankAccount: employeeData.BankAccount,
|
BankAccount: employeeData.BankAccount,
|
||||||
Status: employeeData.Status,
|
Status: int8(employeeData.Status), // 转换为int8
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果没有指定租户ID,从当前登录用户获取(需要JWT中间件支持)
|
// 如果没有指定租户ID,从JWT token中获取
|
||||||
// 这里暂时使用传入的tenant_id,如果为0则使用默认值
|
|
||||||
if employee.TenantId == 0 {
|
if employee.TenantId == 0 {
|
||||||
// 可以从JWT token中获取租户ID,这里暂时设为1作为默认值
|
if tenantId, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantId > 0 {
|
||||||
employee.TenantId = 1
|
employee.TenantId = tenantId
|
||||||
|
} else {
|
||||||
|
c.Data["json"] = map[string]interface{}{
|
||||||
|
"code": 1,
|
||||||
|
"message": "租户ID不能为空",
|
||||||
|
"data": nil,
|
||||||
|
}
|
||||||
|
c.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 默认密码
|
// 默认密码
|
||||||
@ -220,9 +236,10 @@ func (c *EmployeeController) UpdateEmployee() {
|
|||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
DepartmentId int `json:"department_id"`
|
DepartmentId int `json:"department_id"`
|
||||||
PositionId int `json:"position_id"`
|
PositionId int `json:"position_id"`
|
||||||
|
Role int `json:"role"`
|
||||||
BankName string `json:"bank_name"`
|
BankName string `json:"bank_name"`
|
||||||
BankAccount string `json:"bank_account"`
|
BankAccount string `json:"bank_account"`
|
||||||
Status int8 `json:"status"`
|
Status int `json:"status"` // 使用int,前端传递number会自动转换
|
||||||
}
|
}
|
||||||
|
|
||||||
err = json.Unmarshal(c.Ctx.Input.RequestBody, &updateData)
|
err = json.Unmarshal(c.Ctx.Input.RequestBody, &updateData)
|
||||||
@ -254,9 +271,10 @@ func (c *EmployeeController) UpdateEmployee() {
|
|||||||
employee.Email = updateData.Email
|
employee.Email = updateData.Email
|
||||||
employee.DepartmentId = updateData.DepartmentId
|
employee.DepartmentId = updateData.DepartmentId
|
||||||
employee.PositionId = updateData.PositionId
|
employee.PositionId = updateData.PositionId
|
||||||
|
employee.Role = updateData.Role
|
||||||
employee.BankName = updateData.BankName
|
employee.BankName = updateData.BankName
|
||||||
employee.BankAccount = updateData.BankAccount
|
employee.BankAccount = updateData.BankAccount
|
||||||
employee.Status = updateData.Status
|
employee.Status = int8(updateData.Status) // 转换为int8
|
||||||
|
|
||||||
if err := models.UpdateEmployee(employee); err != nil {
|
if err := models.UpdateEmployee(employee); err != nil {
|
||||||
c.Data["json"] = map[string]interface{}{
|
c.Data["json"] = map[string]interface{}{
|
||||||
|
|||||||
@ -24,8 +24,17 @@ func (c *KnowledgeController) List() {
|
|||||||
share, _ := c.GetInt8("share", -1) // Default -1 to query all
|
share, _ := c.GetInt8("share", -1) // Default -1 to query all
|
||||||
keyword := c.GetString("keyword", "")
|
keyword := c.GetString("keyword", "")
|
||||||
|
|
||||||
|
// 获取租户ID(如果是员工登录,从JWT token中获取)
|
||||||
|
tenantId := 0
|
||||||
|
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
|
||||||
|
// 检查是否是员工登录(type === "employee")
|
||||||
|
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
|
||||||
|
tenantId = tenantIdVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Use share in the query
|
// Use share in the query
|
||||||
knowledges, total, err := models.GetAllKnowledge(page, pageSize, status, categoryId, share, keyword)
|
knowledges, total, err := models.GetAllKnowledge(page, pageSize, status, categoryId, share, keyword, tenantId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Data["json"] = map[string]interface{}{
|
c.Data["json"] = map[string]interface{}{
|
||||||
"code": 1,
|
"code": 1,
|
||||||
@ -63,7 +72,16 @@ func (c *KnowledgeController) Detail() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
knowledge, err := models.GetKnowledgeById(id)
|
// 获取租户ID(如果是员工登录,从JWT token中获取)
|
||||||
|
tenantId := 0
|
||||||
|
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
|
||||||
|
// 检查是否是员工登录(type === "employee")
|
||||||
|
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
|
||||||
|
tenantId = tenantIdVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
knowledge, err := models.GetKnowledgeById(id, tenantId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Data["json"] = map[string]interface{}{
|
c.Data["json"] = map[string]interface{}{
|
||||||
"code": 1,
|
"code": 1,
|
||||||
@ -113,6 +131,14 @@ func (c *KnowledgeController) Create() {
|
|||||||
share, _ := c.GetInt8("share", 0)
|
share, _ := c.GetInt8("share", 0)
|
||||||
knowledge.Share = share
|
knowledge.Share = share
|
||||||
|
|
||||||
|
// 获取租户ID(如果是员工登录,从JWT token中获取并设置)
|
||||||
|
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
|
||||||
|
// 检查是否是员工登录(type === "employee")
|
||||||
|
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
|
||||||
|
knowledge.TenantId = tenantIdVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
id, err := models.AddKnowledge(&knowledge)
|
id, err := models.AddKnowledge(&knowledge)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Data["json"] = map[string]interface{}{
|
c.Data["json"] = map[string]interface{}{
|
||||||
@ -159,11 +185,16 @@ func (c *KnowledgeController) Update() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add share parsing
|
// 获取租户ID(如果是员工登录,从JWT token中获取)
|
||||||
share, _ := c.GetInt8("share", 0) // Default 0 if not provided
|
tenantId := 0
|
||||||
knowledge.Share = share
|
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
|
||||||
|
// 检查是否是员工登录(type === "employee")
|
||||||
|
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
|
||||||
|
tenantId = tenantIdVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
err = models.UpdateKnowledge(knowledge.Id, &knowledge)
|
err = models.UpdateKnowledge(knowledge.Id, &knowledge, tenantId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Data["json"] = map[string]interface{}{
|
c.Data["json"] = map[string]interface{}{
|
||||||
"code": 1,
|
"code": 1,
|
||||||
@ -217,7 +248,16 @@ func (c *KnowledgeController) Delete() {
|
|||||||
deleteBy = "system" // 默认值
|
deleteBy = "system" // 默认值
|
||||||
}
|
}
|
||||||
|
|
||||||
err = models.DeleteKnowledge(int(id), deleteBy)
|
// 获取租户ID(如果是员工登录,从JWT token中获取)
|
||||||
|
tenantId := 0
|
||||||
|
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
|
||||||
|
// 检查是否是员工登录(type === "employee")
|
||||||
|
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
|
||||||
|
tenantId = tenantIdVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = models.DeleteKnowledge(int(id), deleteBy, tenantId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Data["json"] = map[string]interface{}{
|
c.Data["json"] = map[string]interface{}{
|
||||||
"code": 1,
|
"code": 1,
|
||||||
@ -239,7 +279,16 @@ func (c *KnowledgeController) Delete() {
|
|||||||
// GetCategories 获取分类列表
|
// GetCategories 获取分类列表
|
||||||
// @router /api/knowledge/categories [get]
|
// @router /api/knowledge/categories [get]
|
||||||
func (c *KnowledgeController) GetCategories() {
|
func (c *KnowledgeController) GetCategories() {
|
||||||
categories, err := models.GetAllCategories()
|
// 获取租户ID(如果是员工登录,从JWT token中获取)
|
||||||
|
tenantId := 0
|
||||||
|
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
|
||||||
|
// 检查是否是员工登录(type === "employee")
|
||||||
|
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
|
||||||
|
tenantId = tenantIdVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
categories, err := models.GetAllCategories(tenantId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Data["json"] = map[string]interface{}{
|
c.Data["json"] = map[string]interface{}{
|
||||||
"code": 1,
|
"code": 1,
|
||||||
@ -275,7 +324,16 @@ func (c *KnowledgeController) GetCategories() {
|
|||||||
// GetTags 获取标签列表
|
// GetTags 获取标签列表
|
||||||
// @router /api/knowledge/tags [get]
|
// @router /api/knowledge/tags [get]
|
||||||
func (c *KnowledgeController) GetTags() {
|
func (c *KnowledgeController) GetTags() {
|
||||||
tags, err := models.GetAllTags()
|
// 获取租户ID(如果是员工登录,从JWT token中获取)
|
||||||
|
tenantId := 0
|
||||||
|
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
|
||||||
|
// 检查是否是员工登录(type === "employee")
|
||||||
|
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
|
||||||
|
tenantId = tenantIdVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tags, err := models.GetAllTags(tenantId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Data["json"] = map[string]interface{}{
|
c.Data["json"] = map[string]interface{}{
|
||||||
"code": 1,
|
"code": 1,
|
||||||
@ -323,6 +381,14 @@ func (c *KnowledgeController) AddCategory() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取租户ID(如果是员工登录,从JWT token中获取并设置)
|
||||||
|
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
|
||||||
|
// 检查是否是员工登录(type === "employee")
|
||||||
|
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
|
||||||
|
category.TenantId = tenantIdVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 不处理id,直接添加,表自动递增
|
// 不处理id,直接添加,表自动递增
|
||||||
_, err = models.AddCategory(&category)
|
_, err = models.AddCategory(&category)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -358,6 +424,14 @@ func (c *KnowledgeController) AddTag() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取租户ID(如果是员工登录,从JWT token中获取并设置)
|
||||||
|
if tenantIdVal, ok := c.Ctx.Input.GetData("tenantId").(int); ok && tenantIdVal > 0 {
|
||||||
|
// 检查是否是员工登录(type === "employee")
|
||||||
|
if userType, ok := c.Ctx.Input.GetData("userType").(string); ok && userType == "employee" {
|
||||||
|
tag.TenantId = tenantIdVal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 判断是添加还是更新
|
// 判断是添加还是更新
|
||||||
if tag.TagId > 0 {
|
if tag.TagId > 0 {
|
||||||
// 更新操作
|
// 更新操作
|
||||||
|
|||||||
@ -34,6 +34,38 @@ func (c *MenuController) GetAllMenus() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTenantMenus 根据角色获取租户菜单(只返回该角色有权限的菜单)
|
||||||
|
// @router /menus/tenant/:roleId [get]
|
||||||
|
func (c *MenuController) GetTenantMenus() {
|
||||||
|
roleId, err := c.GetInt(":roleId")
|
||||||
|
if err != nil || roleId <= 0 {
|
||||||
|
c.Data["json"] = map[string]interface{}{
|
||||||
|
"success": false,
|
||||||
|
"message": "角色ID无效",
|
||||||
|
"data": nil,
|
||||||
|
}
|
||||||
|
c.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
menus, err := models.GetTenantMenus(roleId)
|
||||||
|
if err != nil {
|
||||||
|
c.Data["json"] = map[string]interface{}{
|
||||||
|
"success": false,
|
||||||
|
"message": "获取菜单失败: " + err.Error(),
|
||||||
|
"data": nil,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.Data["json"] = map[string]interface{}{
|
||||||
|
"success": true,
|
||||||
|
"message": "获取菜单成功",
|
||||||
|
"data": menus,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
// CreateMenu 创建新菜单
|
// CreateMenu 创建新菜单
|
||||||
func (c *MenuController) CreateMenu() {
|
func (c *MenuController) CreateMenu() {
|
||||||
var menu models.Menu
|
var menu models.Menu
|
||||||
|
|||||||
@ -77,6 +77,8 @@ func (c *UserController) GetTenantUsers() {
|
|||||||
"tenant_id": user.TenantId,
|
"tenant_id": user.TenantId,
|
||||||
"status": user.Status,
|
"status": user.Status,
|
||||||
"role": user.Role,
|
"role": user.Role,
|
||||||
|
"department_id": user.DepartmentId,
|
||||||
|
"position_id": user.PositionId,
|
||||||
"last_login_time": user.LastLoginTime,
|
"last_login_time": user.LastLoginTime,
|
||||||
"last_login_ip": user.LastLoginIp,
|
"last_login_ip": user.LastLoginIp,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -64,5 +64,13 @@ func JWTAuthMiddleware() web.FilterFunc {
|
|||||||
ctx.Input.SetData("userId", claims.UserID)
|
ctx.Input.SetData("userId", claims.UserID)
|
||||||
ctx.Input.SetData("username", claims.Username)
|
ctx.Input.SetData("username", claims.Username)
|
||||||
ctx.Input.SetData("tenantId", claims.TenantId)
|
ctx.Input.SetData("tenantId", claims.TenantId)
|
||||||
|
|
||||||
|
// 判断用户类型:检查userId是否在员工表中
|
||||||
|
// 如果userId在yz_tenant_employees表中存在,则为员工登录;否则为用户登录
|
||||||
|
userType := "user"
|
||||||
|
if models.IsEmployee(claims.UserID) {
|
||||||
|
userType = "employee"
|
||||||
|
}
|
||||||
|
ctx.Input.SetData("userType", userType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@ type Employee struct {
|
|||||||
Email string `orm:"size(100);null" json:"email"`
|
Email string `orm:"size(100);null" json:"email"`
|
||||||
DepartmentId int `orm:"column(department_id);null;default(0)" json:"department_id"`
|
DepartmentId int `orm:"column(department_id);null;default(0)" json:"department_id"`
|
||||||
PositionId int `orm:"column(position_id);null;default(0)" json:"position_id"`
|
PositionId int `orm:"column(position_id);null;default(0)" json:"position_id"`
|
||||||
|
Role int `orm:"column(role);null;default(0)" json:"role"` // 角色ID
|
||||||
BankName string `orm:"column(bank_name);size(100);null" json:"bank_name"`
|
BankName string `orm:"column(bank_name);size(100);null" json:"bank_name"`
|
||||||
BankAccount string `orm:"column(bank_account);size(50);null" json:"bank_account"`
|
BankAccount string `orm:"column(bank_account);size(50);null" json:"bank_account"`
|
||||||
Password string `orm:"size(255);null" json:"-"` // 不返回给前端
|
Password string `orm:"size(255);null" json:"-"` // 不返回给前端
|
||||||
@ -121,7 +122,7 @@ func AddEmployee(employee *Employee, defaultPassword string) (int64, error) {
|
|||||||
// UpdateEmployee 更新员工信息
|
// UpdateEmployee 更新员工信息
|
||||||
func UpdateEmployee(employee *Employee) error {
|
func UpdateEmployee(employee *Employee) error {
|
||||||
o := orm.NewOrm()
|
o := orm.NewOrm()
|
||||||
_, err := o.Update(employee, "employee_no", "name", "phone", "email", "department_id", "position_id", "bank_name", "bank_account", "status", "update_time")
|
_, err := o.Update(employee, "employee_no", "name", "phone", "email", "department_id", "position_id", "role", "bank_name", "bank_account", "status", "update_time")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,3 +241,18 @@ func GetAllEmployees() ([]*Employee, error) {
|
|||||||
return employees, err
|
return employees, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsEmployee 检查指定的ID是否是员工(用于判断登录类型)
|
||||||
|
func IsEmployee(id int) bool {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
employee := &Employee{Id: id}
|
||||||
|
err := o.Read(employee)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// 检查是否已删除
|
||||||
|
if employee.DeleteTime != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
// Knowledge 知识库模型
|
// Knowledge 知识库模型
|
||||||
type Knowledge struct {
|
type Knowledge struct {
|
||||||
Id int `orm:"column(knowledge_id);pk;auto" json:"id"`
|
Id int `orm:"column(knowledge_id);pk;auto" json:"id"`
|
||||||
|
TenantId int `orm:"column(tenant_id);default(0)" json:"tenantId"`
|
||||||
Title string `orm:"column(title);size(200)" json:"title"`
|
Title string `orm:"column(title);size(200)" json:"title"`
|
||||||
CategoryId int `orm:"column(category_id);default(0);null" json:"categoryId"`
|
CategoryId int `orm:"column(category_id);default(0);null" json:"categoryId"`
|
||||||
CategoryName string `orm:"-" json:"categoryName"` // 不映射到数据库,从联查获取
|
CategoryName string `orm:"-" json:"categoryName"` // 不映射到数据库,从联查获取
|
||||||
@ -39,6 +40,7 @@ func (k *Knowledge) TableName() string {
|
|||||||
// KnowledgeCategory 知识库分类模型
|
// KnowledgeCategory 知识库分类模型
|
||||||
type KnowledgeCategory struct {
|
type KnowledgeCategory struct {
|
||||||
CategoryId int `orm:"column(category_id);pk;auto" json:"categoryId"`
|
CategoryId int `orm:"column(category_id);pk;auto" json:"categoryId"`
|
||||||
|
TenantId int `orm:"column(tenant_id);default(0)" json:"tenantId"`
|
||||||
CategoryName string `orm:"column(category_name);size(100)" json:"categoryName"`
|
CategoryName string `orm:"column(category_name);size(100)" json:"categoryName"`
|
||||||
CategoryDesc string `orm:"column(category_desc);size(500);null" json:"categoryDesc"`
|
CategoryDesc string `orm:"column(category_desc);size(500);null" json:"categoryDesc"`
|
||||||
ParentId int `orm:"column(parent_id);default(0)" json:"parentId"`
|
ParentId int `orm:"column(parent_id);default(0)" json:"parentId"`
|
||||||
@ -55,7 +57,8 @@ func (kc *KnowledgeCategory) TableName() string {
|
|||||||
// KnowledgeTag 知识库标签模型
|
// KnowledgeTag 知识库标签模型
|
||||||
type KnowledgeTag struct {
|
type KnowledgeTag struct {
|
||||||
TagId int `orm:"column(tag_id);pk;auto" json:"tagId"`
|
TagId int `orm:"column(tag_id);pk;auto" json:"tagId"`
|
||||||
TagName string `orm:"column(tag_name);size(50);unique" json:"tagName"`
|
TenantId int `orm:"column(tenant_id);default(0)" json:"tenantId"`
|
||||||
|
TagName string `orm:"column(tag_name);size(50)" json:"tagName"`
|
||||||
TagColor string `orm:"column(tag_color);size(20);null" json:"tagColor"`
|
TagColor string `orm:"column(tag_color);size(20);null" json:"tagColor"`
|
||||||
TagBackground string `orm:"column(tag_background);size(20);null" json:"tagBackground"`
|
TagBackground string `orm:"column(tag_background);size(20);null" json:"tagBackground"`
|
||||||
UsageCount int `orm:"column(usage_count);default(0)" json:"usageCount"`
|
UsageCount int `orm:"column(usage_count);default(0)" json:"usageCount"`
|
||||||
@ -76,7 +79,7 @@ func AddKnowledge(k *Knowledge) (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetKnowledgeById 根据ID获取知识详情(使用联查获取分类名称)
|
// GetKnowledgeById 根据ID获取知识详情(使用联查获取分类名称)
|
||||||
func GetKnowledgeById(id int) (*Knowledge, error) {
|
func GetKnowledgeById(id int, tenantId int) (*Knowledge, error) {
|
||||||
o := orm.NewOrm()
|
o := orm.NewOrm()
|
||||||
|
|
||||||
// 使用联查获取分类名称(只查询未删除的记录)
|
// 使用联查获取分类名称(只查询未删除的记录)
|
||||||
@ -86,6 +89,13 @@ func GetKnowledgeById(id int) (*Knowledge, error) {
|
|||||||
LEFT JOIN yz_knowledge_category c ON k.category_id = c.category_id
|
LEFT JOIN yz_knowledge_category c ON k.category_id = c.category_id
|
||||||
WHERE k.knowledge_id = ? AND k.delete_time IS NULL
|
WHERE k.knowledge_id = ? AND k.delete_time IS NULL
|
||||||
`
|
`
|
||||||
|
params := []interface{}{id}
|
||||||
|
|
||||||
|
// 如果tenantId > 0,添加租户过滤
|
||||||
|
if tenantId > 0 {
|
||||||
|
querySQL += " AND k.tenant_id = ?"
|
||||||
|
params = append(params, tenantId)
|
||||||
|
}
|
||||||
|
|
||||||
var result struct {
|
var result struct {
|
||||||
Id int `orm:"column(knowledge_id)"`
|
Id int `orm:"column(knowledge_id)"`
|
||||||
@ -108,7 +118,7 @@ func GetKnowledgeById(id int) (*Knowledge, error) {
|
|||||||
UpdateBy string `orm:"column(update_by)"`
|
UpdateBy string `orm:"column(update_by)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
err := o.Raw(querySQL, id).QueryRow(&result)
|
err := o.Raw(querySQL, params...).QueryRow(&result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -165,12 +175,18 @@ func addCondition(where *string, params *[]interface{}, cond string, val interfa
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetAllKnowledge (simplified: direct mapping to LightKnowledge, no separate struct or loop)
|
// GetAllKnowledge (simplified: direct mapping to LightKnowledge, no separate struct or loop)
|
||||||
func GetAllKnowledge(page, pageSize int, status int8, categoryId int, share int8, keyword string) ([]*LightKnowledge, int64, error) {
|
func GetAllKnowledge(page, pageSize int, status int8, categoryId int, share int8, keyword string, tenantId int) ([]*LightKnowledge, int64, error) {
|
||||||
o := orm.NewOrm()
|
o := orm.NewOrm()
|
||||||
|
|
||||||
whereSQL := "delete_time IS NULL"
|
whereSQL := "delete_time IS NULL"
|
||||||
params := []interface{}{}
|
params := []interface{}{}
|
||||||
|
|
||||||
|
// 如果tenantId > 0,添加租户过滤
|
||||||
|
if tenantId > 0 {
|
||||||
|
whereSQL += " AND k.tenant_id = ?"
|
||||||
|
params = append(params, tenantId)
|
||||||
|
}
|
||||||
|
|
||||||
addCondition(&whereSQL, ¶ms, "status = ?", func() interface{} {
|
addCondition(&whereSQL, ¶ms, "status = ?", func() interface{} {
|
||||||
if status >= 0 {
|
if status >= 0 {
|
||||||
return status
|
return status
|
||||||
@ -197,7 +213,7 @@ func GetAllKnowledge(page, pageSize int, status int8, categoryId int, share int8
|
|||||||
}())
|
}())
|
||||||
|
|
||||||
var total int64
|
var total int64
|
||||||
err := o.Raw("SELECT COUNT(*) FROM yz_knowledge WHERE "+whereSQL, params).QueryRow(&total)
|
err := o.Raw("SELECT COUNT(*) FROM yz_knowledge k WHERE "+whereSQL, params).QueryRow(&total)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
@ -217,7 +233,7 @@ func GetAllKnowledge(page, pageSize int, status int8, categoryId int, share int8
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateKnowledge 更新知识
|
// UpdateKnowledge 更新知识
|
||||||
func UpdateKnowledge(id int, k *Knowledge) error {
|
func UpdateKnowledge(id int, k *Knowledge, tenantId int) error {
|
||||||
o := orm.NewOrm()
|
o := orm.NewOrm()
|
||||||
knowledge := &Knowledge{Id: id}
|
knowledge := &Knowledge{Id: id}
|
||||||
err := o.Read(knowledge)
|
err := o.Read(knowledge)
|
||||||
@ -225,6 +241,11 @@ func UpdateKnowledge(id int, k *Knowledge) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果tenantId > 0,验证租户ID是否匹配
|
||||||
|
if tenantId > 0 && knowledge.TenantId != tenantId {
|
||||||
|
return orm.ErrNoRows // 返回无记录错误,表示该知识不属于当前租户
|
||||||
|
}
|
||||||
|
|
||||||
// 更新字段
|
// 更新字段
|
||||||
knowledge.Title = k.Title
|
knowledge.Title = k.Title
|
||||||
knowledge.CategoryId = k.CategoryId
|
knowledge.CategoryId = k.CategoryId
|
||||||
@ -234,16 +255,17 @@ func UpdateKnowledge(id int, k *Knowledge) error {
|
|||||||
knowledge.Summary = k.Summary
|
knowledge.Summary = k.Summary
|
||||||
knowledge.CoverUrl = k.CoverUrl
|
knowledge.CoverUrl = k.CoverUrl
|
||||||
knowledge.Status = k.Status
|
knowledge.Status = k.Status
|
||||||
|
knowledge.Share = k.Share
|
||||||
knowledge.IsRecommend = k.IsRecommend
|
knowledge.IsRecommend = k.IsRecommend
|
||||||
knowledge.IsTop = k.IsTop
|
knowledge.IsTop = k.IsTop
|
||||||
knowledge.UpdateBy = k.UpdateBy
|
knowledge.UpdateBy = k.UpdateBy
|
||||||
|
|
||||||
_, err = o.Update(knowledge, "title", "category_id", "tags", "author", "content", "summary", "cover_url", "status", "is_recommend", "is_top", "update_by", "update_time")
|
_, err = o.Update(knowledge, "title", "category_id", "tags", "author", "content", "summary", "cover_url", "status", "share", "is_recommend", "is_top", "update_by", "update_time")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteKnowledge 软删除知识
|
// DeleteKnowledge 软删除知识
|
||||||
func DeleteKnowledge(id int, deleteBy string) error {
|
func DeleteKnowledge(id int, deleteBy string, tenantId int) error {
|
||||||
o := orm.NewOrm()
|
o := orm.NewOrm()
|
||||||
knowledge := &Knowledge{Id: id}
|
knowledge := &Knowledge{Id: id}
|
||||||
err := o.Read(knowledge)
|
err := o.Read(knowledge)
|
||||||
@ -251,16 +273,28 @@ func DeleteKnowledge(id int, deleteBy string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果tenantId > 0,验证租户ID是否匹配
|
||||||
|
if tenantId > 0 && knowledge.TenantId != tenantId {
|
||||||
|
return orm.ErrNoRows // 返回无记录错误,表示该知识不属于当前租户
|
||||||
|
}
|
||||||
|
|
||||||
// 执行软删除:设置 delete_time 和 delete_by
|
// 执行软删除:设置 delete_time 和 delete_by
|
||||||
_, err = o.Raw("UPDATE yz_knowledge SET delete_time = ?, delete_by = ? WHERE knowledge_id = ?", time.Now(), deleteBy, id).Exec()
|
_, err = o.Raw("UPDATE yz_knowledge SET delete_time = ?, delete_by = ? WHERE knowledge_id = ?", time.Now(), deleteBy, id).Exec()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllCategories 获取所有分类
|
// GetAllCategories 获取所有分类
|
||||||
func GetAllCategories() ([]*KnowledgeCategory, error) {
|
func GetAllCategories(tenantId int) ([]*KnowledgeCategory, error) {
|
||||||
o := orm.NewOrm()
|
o := orm.NewOrm()
|
||||||
|
qs := o.QueryTable("yz_knowledge_category")
|
||||||
|
|
||||||
|
// 如果tenantId > 0,添加租户过滤
|
||||||
|
if tenantId > 0 {
|
||||||
|
qs = qs.Filter("tenant_id", tenantId)
|
||||||
|
}
|
||||||
|
|
||||||
var categories []*KnowledgeCategory
|
var categories []*KnowledgeCategory
|
||||||
_, err := o.QueryTable("yz_knowledge_category").OrderBy("sort_order").All(&categories)
|
_, err := qs.OrderBy("sort_order").All(&categories)
|
||||||
return categories, err
|
return categories, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,10 +307,17 @@ func GetCategoryById(id int) (*KnowledgeCategory, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetAllTags 获取所有标签
|
// GetAllTags 获取所有标签
|
||||||
func GetAllTags() ([]*KnowledgeTag, error) {
|
func GetAllTags(tenantId int) ([]*KnowledgeTag, error) {
|
||||||
o := orm.NewOrm()
|
o := orm.NewOrm()
|
||||||
|
qs := o.QueryTable("yz_knowledge_tags")
|
||||||
|
|
||||||
|
// 如果tenantId > 0,添加租户过滤
|
||||||
|
if tenantId > 0 {
|
||||||
|
qs = qs.Filter("tenant_id", tenantId)
|
||||||
|
}
|
||||||
|
|
||||||
var tags []*KnowledgeTag
|
var tags []*KnowledgeTag
|
||||||
_, err := o.QueryTable("yz_knowledge_tags").All(&tags)
|
_, err := qs.All(&tags)
|
||||||
return tags, err
|
return tags, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/beego/beego/v2/client/orm"
|
"github.com/beego/beego/v2/client/orm"
|
||||||
@ -96,3 +97,70 @@ func DeleteMenu(id int) error {
|
|||||||
_, err := o.Update(&menu, "DeleteTime")
|
_, err := o.Update(&menu, "DeleteTime")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTenantMenus 根据角色ID获取租户菜单(只返回该角色有权限的菜单,且只返回页面菜单menu_type=1)
|
||||||
|
func GetTenantMenus(roleId int) ([]map[string]interface{}, error) {
|
||||||
|
o := orm.NewOrm()
|
||||||
|
|
||||||
|
// 如果角色ID为0或无效,返回空列表
|
||||||
|
if roleId <= 0 {
|
||||||
|
return []map[string]interface{}{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 从yz_role_menus表获取该角色的所有菜单ID
|
||||||
|
var menuIds []int
|
||||||
|
_, err := o.Raw("SELECT DISTINCT menu_id FROM yz_role_menus WHERE role_id = ?", roleId).QueryRows(&menuIds)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有权限,返回空列表
|
||||||
|
if len(menuIds) == 0 {
|
||||||
|
return []map[string]interface{}{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 构建IN查询的占位符
|
||||||
|
placeholders := make([]string, len(menuIds))
|
||||||
|
args := make([]interface{}, len(menuIds)+1)
|
||||||
|
for i, id := range menuIds {
|
||||||
|
placeholders[i] = "?"
|
||||||
|
args[i] = id
|
||||||
|
}
|
||||||
|
args[len(menuIds)] = 1 // menu_type=1 表示页面菜单
|
||||||
|
|
||||||
|
// 3. 查询菜单(只返回menu_type=1的页面菜单,且未删除的)
|
||||||
|
query := "SELECT id, name, path, parent_id, icon, `order`, status, component_path, is_external, external_url, menu_type, permission " +
|
||||||
|
"FROM yz_menus " +
|
||||||
|
"WHERE id IN (" + strings.Join(placeholders, ",") + ") " +
|
||||||
|
"AND delete_time IS NULL " +
|
||||||
|
"AND menu_type = ? " +
|
||||||
|
"ORDER BY `order`, id"
|
||||||
|
|
||||||
|
var menus []*Menu
|
||||||
|
_, err = o.Raw(query, args...).QueryRows(&menus)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 转换为map格式
|
||||||
|
result := make([]map[string]interface{}, 0, len(menus))
|
||||||
|
for _, m := range menus {
|
||||||
|
item := map[string]interface{}{
|
||||||
|
"id": m.Id,
|
||||||
|
"name": m.Name,
|
||||||
|
"path": m.Path,
|
||||||
|
"parentId": m.ParentId,
|
||||||
|
"icon": m.Icon,
|
||||||
|
"order": m.Order,
|
||||||
|
"status": m.Status,
|
||||||
|
"componentPath": m.ComponentPath,
|
||||||
|
"isExternal": m.IsExternal,
|
||||||
|
"externalUrl": m.ExternalUrl,
|
||||||
|
"menuType": m.MenuType,
|
||||||
|
"permission": m.Permission,
|
||||||
|
}
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|||||||
@ -249,6 +249,7 @@ func init() {
|
|||||||
beego.Router("/api/menu/:id", &controllers.MenuController{}, "put:UpdateMenu")
|
beego.Router("/api/menu/:id", &controllers.MenuController{}, "put:UpdateMenu")
|
||||||
beego.Router("/api/menu/:id", &controllers.MenuController{}, "delete:DeleteMenu")
|
beego.Router("/api/menu/:id", &controllers.MenuController{}, "delete:DeleteMenu")
|
||||||
beego.Router("/api/menu/status/:id", &controllers.MenuController{}, "patch:UpdateMenuStatus")
|
beego.Router("/api/menu/status/:id", &controllers.MenuController{}, "patch:UpdateMenuStatus")
|
||||||
|
beego.Router("/api/menus/tenant/:roleId", &controllers.MenuController{}, "get:GetTenantMenus")
|
||||||
|
|
||||||
// 程序分类路由 - 自动映射到 /api/programcategory/*
|
// 程序分类路由 - 自动映射到 /api/programcategory/*
|
||||||
beego.AutoRouter(&controllers.ProgramCategoryController{})
|
beego.AutoRouter(&controllers.ProgramCategoryController{})
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user