diff --git a/rc_autoplc_front/.env.development b/rc_autoplc_front/.env.development index 8aaa774..4d37822 100644 --- a/rc_autoplc_front/.env.development +++ b/rc_autoplc_front/.env.development @@ -1 +1 @@ -VITE_API_URL=http://192.168.110.204:9090 +VITE_API_URL=http://223.71.122.54:9090 diff --git a/rc_autoplc_front/.env.production b/rc_autoplc_front/.env.production index 8aaa774..4d37822 100644 --- a/rc_autoplc_front/.env.production +++ b/rc_autoplc_front/.env.production @@ -1 +1 @@ -VITE_API_URL=http://192.168.110.204:9090 +VITE_API_URL=http://223.71.122.54:9090 diff --git a/rc_autoplc_front/src/api/business/islandinfo.ts b/rc_autoplc_front/src/api/business/islandinfo.ts new file mode 100644 index 0000000..fbd1bae --- /dev/null +++ b/rc_autoplc_front/src/api/business/islandinfo.ts @@ -0,0 +1,39 @@ +import request from '@/utils/request' + +export function islandInfoadd(data: any) { + return request({ + url: '/islandInfo/add', + method: 'post', + data, + }) +} + +export function islandInfodel(id: string | number) { + return request({ + url: `/islandInfo/del/${id}`, + method: 'delete', + }) +} + +export function islandInfoupd(data: any) { + return request({ + url: '/islandInfo/update', + method: 'put', + data, + }) +} + +export function islandInfolist(data: any) { + return request({ + url: '/islandInfo/listPage', + method: 'get', + params: data, + }) +} + +export function islandInfobyid(id: string | number) { + return request({ + url: `/islandInfo/getById/${id}`, + method: 'get', + }) +} \ No newline at end of file diff --git a/rc_autoplc_front/src/api/department.ts b/rc_autoplc_front/src/api/system/department.ts similarity index 100% rename from rc_autoplc_front/src/api/department.ts rename to rc_autoplc_front/src/api/system/department.ts diff --git a/rc_autoplc_front/src/api/manage-log.ts b/rc_autoplc_front/src/api/system/manage-log.ts similarity index 100% rename from rc_autoplc_front/src/api/manage-log.ts rename to rc_autoplc_front/src/api/system/manage-log.ts diff --git a/rc_autoplc_front/src/api/position.ts b/rc_autoplc_front/src/api/system/position.ts similarity index 96% rename from rc_autoplc_front/src/api/position.ts rename to rc_autoplc_front/src/api/system/position.ts index 50053d7..c131d2a 100644 --- a/rc_autoplc_front/src/api/position.ts +++ b/rc_autoplc_front/src/api/system/position.ts @@ -25,7 +25,7 @@ export function positionupd(data: any) { export function positionlist(data: any) { return request({ - url: '/position/listPpage', + url: '/position/listPage', method: 'get', params: data, }) diff --git a/rc_autoplc_front/src/api/role.ts b/rc_autoplc_front/src/api/system/role.ts similarity index 83% rename from rc_autoplc_front/src/api/role.ts rename to rc_autoplc_front/src/api/system/role.ts index 0431cbc..5bbf493 100644 --- a/rc_autoplc_front/src/api/role.ts +++ b/rc_autoplc_front/src/api/system/role.ts @@ -36,4 +36,12 @@ export function rolebyid(id: string | number) { url: `/role/getById/${id}`, method: 'get', }) +} + +export function rleselect(data: any) { + return request({ + url: '/role/list', + method: 'get', + params: data, + }) } \ No newline at end of file diff --git a/rc_autoplc_front/src/api/system/user-role.ts b/rc_autoplc_front/src/api/system/user-role.ts new file mode 100644 index 0000000..9d65c25 --- /dev/null +++ b/rc_autoplc_front/src/api/system/user-role.ts @@ -0,0 +1,67 @@ +import request from '@/utils/request' + +// 新增用户角色关联 +export function userRoleAdd(data: any) { + return request({ + url: '/user-role/add', + method: 'post', + data, + }) +} + +// 根据ID删除用户角色关联 +export function userRoleDel(id: string | number) { + return request({ + url: `/user-role/del/${id}`, + method: 'delete', + }) +} + +// 分页查询用户角色关联列表 +export function userRoleList(data: any) { + return request({ + url: '/user-role/listPage', + method: 'get', + params: data, + }) +} + +// 根据ID查询用户角色关联 +export function userRoleById(id: string | number) { + return request({ + url: `/user-role/getById/${id}`, + method: 'get', + }) +} + +// 根据角色ID查询关联用户(先封装不调用) +export function userRoleByRoleId(roleId: string | number) { + return request({ + url: `/user-role/getByRoleId/${roleId}`, + method: 'get', + }) +} + +// 根据角色ID删除所有关联(先封装不调用) +export function userRoleDelByRoleId(roleId: string | number) { + return request({ + url: `/user-role/delByRoleId/${roleId}`, + method: 'delete', + }) +} + +// 根据用户ID查询关联角色(先封装不调用) +export function userRoleByUserId(userId: string | number) { + return request({ + url: `/user-role/getByUserId/${userId}`, + method: 'get', + }) +} + +// 根据用户ID删除所有关联(先封装不调用) +export function userRoleDelByUserId(userId: string | number) { + return request({ + url: `/user-role/delByUserId/${userId}`, + method: 'delete', + }) +} diff --git a/rc_autoplc_front/src/api/user.ts b/rc_autoplc_front/src/api/system/user.ts similarity index 83% rename from rc_autoplc_front/src/api/user.ts rename to rc_autoplc_front/src/api/system/user.ts index 6a3ea39..9c032ef 100644 --- a/rc_autoplc_front/src/api/user.ts +++ b/rc_autoplc_front/src/api/system/user.ts @@ -31,6 +31,14 @@ export function userlist(data: any) { }) } +export function userselect(data: any) { + return request({ + url: '/user/list', + method: 'get', + params: data, + }) +} + export function userbyid(id: string | number) { return request({ url: `/user/getById/${id}`, diff --git a/rc_autoplc_front/src/router/index.ts b/rc_autoplc_front/src/router/index.ts index f1a2835..b6c6386 100644 --- a/rc_autoplc_front/src/router/index.ts +++ b/rc_autoplc_front/src/router/index.ts @@ -5,28 +5,39 @@ const router = createRouter({ routes: [ { path: '/', - name: 'user', - component: () => import('../views/user/index.vue'), - }, - { - path: '/role', - name: 'role', - component: () => import('../views/role/index.vue'), - }, - { - path: '/department', - name: 'department', - component: () => import('../views/department/index.vue'), - }, - { - path: '/position', - name: 'position', - component: () => import('../views/position/index.vue'), - }, - { - path: '/manage-log', - name: 'manage-log', - component: () => import('../views/manage-log/index.vue'), + component: () => import('../views/Layout.vue'), + children: [ + { + path: '/user', + name: 'user', + component: () => import('../views/user/index.vue'), + }, + { + path: '/role', + name: 'role', + component: () => import('../views/role/index.vue'), + }, + { + path: '/department', + name: 'department', + component: () => import('../views/department/index.vue'), + }, + { + path: '/position', + name: 'position', + component: () => import('../views/position/index.vue'), + }, + { + path: '/manage-log', + name: 'manage-log', + component: () => import('../views/manage-log/index.vue'), + }, + { + path: '/user-role', + name: 'user-role', + component: () => import('../views/user-role/index.vue'), + }, + ], }, ], }) diff --git a/rc_autoplc_front/src/views/Layout.vue b/rc_autoplc_front/src/views/Layout.vue new file mode 100644 index 0000000..2a35ff0 --- /dev/null +++ b/rc_autoplc_front/src/views/Layout.vue @@ -0,0 +1,195 @@ + + + + + + diff --git a/rc_autoplc_front/src/views/department/index.vue b/rc_autoplc_front/src/views/department/index.vue index 6cec064..25c0e66 100644 --- a/rc_autoplc_front/src/views/department/index.vue +++ b/rc_autoplc_front/src/views/department/index.vue @@ -88,10 +88,10 @@ :formatter="formatCell" /> @@ -160,13 +160,13 @@ v-model="form.leaderId" filterable clearable - placeholder="请选择部门领导(可选)" + placeholder="请选择部门领导" style="width: 100%" > @@ -205,7 +205,8 @@ import { departmentadd, departmentdel, departtree, -} from '@/api/department' +} from '@/api/system/department' +import { userselect } from '@/api/system/user' interface DeptItem { id?: number | string @@ -227,6 +228,7 @@ interface UserItem { username?: string realName?: string nickName?: string + nicke?: string name?: string } @@ -285,6 +287,18 @@ const formatCell = (_row: any, _column: any, value: any) => { return value === undefined || value === null || value === '' ? '暂无' : value } +// 根据leaderId获取用户的nicke字段 +const getLeaderNicke = (leaderId: number | string | null | undefined): string => { + if (!leaderId) return '暂无' + const user = userOptions.value.find(u => u.id == leaderId) + return user?.nicke || user?.realName || user?.nickName || user?.username || user?.name || '暂无' +} + +// 部门领导列的formatter +const formatLeaderCell = (_row: any, _column: any, _value: any) => { + return getLeaderNicke(_row.leaderId) +} + // 构建树形选择器的选项 const treeOptions = computed(() => { const buildOptions = (nodes: DeptItem[], excludeId?: number | string): any[] => { @@ -347,15 +361,14 @@ const handleTreeReset = () => { // 加载用户列表(用于选择部门领导) const loadUsers = async () => { try { - // 这里需要根据实际API调整,暂时使用空数组 - // 如果有用户列表API,可以在这里调用 - // const res: any = await userlist({ pageNum: 1, pageSize: 9999 }) - // const data = res?.data ?? res ?? {} - // const records = data.records || data.list || data.rows || data.items || [] - // userOptions.value = Array.isArray(records) ? records : [] - userOptions.value = [] + const res: any = await userselect({}) + // 兼容多种返回格式:res.data 或 res 本身 + const data = Array.isArray(res?.data) ? res.data : Array.isArray(res) ? res : [] + userOptions.value = data } catch (error) { console.error('load user list error', error) + ElMessage.error('加载用户列表失败') + userOptions.value = [] } } @@ -363,6 +376,11 @@ const loadUsers = async () => { const loadList = async () => { loading.value = true try { + // 确保用户列表已加载(用于显示部门领导名称) + if (userOptions.value.length === 0) { + await loadUsers() + } + // 构建查询参数,过滤空字符串 const params: any = { pageNum: pagination.pageNum, @@ -652,3 +670,4 @@ onMounted(() => { } + diff --git a/rc_autoplc_front/src/views/manage-log/index.vue b/rc_autoplc_front/src/views/manage-log/index.vue index d662b3b..d0969b4 100644 --- a/rc_autoplc_front/src/views/manage-log/index.vue +++ b/rc_autoplc_front/src/views/manage-log/index.vue @@ -1,20 +1,28 @@ @@ -220,9 +246,11 @@ import { onMounted, reactive, ref, computed } from 'vue' import type { FormInstance, FormRules } from 'element-plus' import { ElMessage, ElMessageBox } from 'element-plus' -import { useradd, userbyid, userdel, userlist, userupd } from '@/api/user' -import { departtree } from '@/api/department' -import { positionselect } from '@/api/position' +import { useradd, userbyid, userdel, userlist, userupd } from '@/api/system/user' +import { departtree } from '@/api/system/department' +import { positionselect } from '@/api/system/position' +import { userRoleAdd, userRoleByUserId, userRoleDel } from '@/api/system/user-role' +import { rleselect } from '@/api/system/role' interface UserItem { id?: number | string @@ -253,6 +281,12 @@ interface PositionItem { posiCode?: string } +interface RoleItem { + id?: number | string + roleName?: string + roleCode?: string +} + const loading = ref(false) const submitLoading = ref(false) const tableData = ref([]) @@ -261,6 +295,12 @@ const deptTreeData = ref([]) const positionOptions = ref([]) const deptMap = ref>(new Map()) const posMap = ref>(new Map()) +const roleDialogVisible = ref(false) +const assignRoleLoading = ref(false) +const roleOptions = ref([]) +const selectedRoleIds = ref<(number | string)[]>([]) +const currentAssignUserId = ref(null) +const originalUserRoles = ref([]) // 保存用户原有的角色关联列表 const queryForm = reactive({ userName: '', @@ -638,9 +678,128 @@ const handleDelete = (row: UserItem) => { .catch(() => {}) } +// 加载角色列表 +const loadRoleList = async () => { + try { + const res: any = await rleselect({}) + const data = Array.isArray(res?.data) ? res.data : Array.isArray(res) ? res : [] + roleOptions.value = data + } catch (error) { + console.error('load role list error', error) + ElMessage.error('加载角色列表失败') + roleOptions.value = [] + } +} + +// 打开角色分配弹框 +const openRoleDialog = async (row: UserItem) => { + if (!row.id) { + ElMessage.warning('缺少用户ID') + return + } + currentAssignUserId.value = row.id + selectedRoleIds.value = [] + roleDialogVisible.value = true + + // 确保角色列表已加载 + if (roleOptions.value.length === 0) { + await loadRoleList() + } + + // 获取用户已有的角色 + try { + const res: any = await userRoleByUserId(row.id) + const data = res?.data ?? res ?? {} + + // 兼容多种返回格式 + const userRoles = Array.isArray(data) + ? data + : Array.isArray(data.data) + ? data.data + : Array.isArray(data.records) + ? data.records + : Array.isArray(data.list) + ? data.list + : [] + + // 保存原有的角色关联列表(包含ID) + originalUserRoles.value = userRoles + + // 提取已有角色的ID列表 + if (Array.isArray(userRoles) && userRoles.length > 0) { + selectedRoleIds.value = userRoles + .map((item: any) => item.roleId) + .filter((id: any) => id !== undefined && id !== null) + } else { + selectedRoleIds.value = [] + originalUserRoles.value = [] + } + } catch (error) { + console.error('load user roles error', error) + // 如果获取失败,不影响弹框打开,只是不预选角色 + originalUserRoles.value = [] + } +} + +// 分配角色 +const handleAssignRole = async () => { + if (!currentAssignUserId.value) { + ElMessage.warning('缺少用户ID') + return + } + + assignRoleLoading.value = true + try { + // 获取原有的角色ID列表 + const originalRoleIds = originalUserRoles.value + .map((item: any) => item.roleId) + .filter((id: any) => id !== undefined && id !== null) + + // 计算需要新增的角色(新选中但原来没有的) + const rolesToAdd = selectedRoleIds.value.filter( + (roleId) => !originalRoleIds.includes(roleId) + ) + + // 计算需要删除的角色(原来有但现在未选中的) + const rolesToDelete = originalUserRoles.value.filter( + (item: any) => !selectedRoleIds.value.includes(item.roleId) + ) + + // 执行新增操作 + const addPromises = rolesToAdd.map((roleId) => { + return userRoleAdd({ + userId: currentAssignUserId.value, + roleId: roleId, + remark: '', + }) + }) + + // 执行删除操作 + const deletePromises = rolesToDelete.map((item: any) => { + if (item.id) { + return userRoleDel(item.id) + } + return Promise.resolve() + }) + + // 等待所有操作完成 + await Promise.all([...addPromises, ...deletePromises]) + + ElMessage.success('分配角色成功') + roleDialogVisible.value = false + } catch (error: any) { + console.error('assign role error', error) + const errorMsg = error?.message || error?.msg || '分配角色失败' + ElMessage.error(errorMsg) + } finally { + assignRoleLoading.value = false + } +} + onMounted(() => { loadDeptTree() loadPositionList() + loadRoleList() loadList() })