大屏项目初始化

This commit is contained in:
2026-03-08 13:05:57 +08:00
parent a052721622
commit f14cde0287
19 changed files with 329 additions and 357 deletions

View File

@@ -9,4 +9,15 @@ export function getHomeModuleList(params) {
method: 'get',
params: params
})
}
/**
* 删除信息列表
*/
export function getHomeModuleDelete(params) {
return request({
url: '/biz/homeModule/delete',
method: 'post',
params: params
})
}

View File

@@ -0,0 +1,34 @@
import request from '@/utils/request'
/**
* 获取指标信息列表
*/
export function getHomeModuleUserList(params) {
return request({
url: '/biz/homeModuleUser/userList',
method: 'get',
params: params
})
}
/**
* 保存信息列表
*/
export function getHomeModuleUserSave(data) {
return request({
url: '/biz/homeModuleUser/save',
method: 'post',
data
})
}
/**
* 删除信息列表
*/
export function getHomeModuleUserDelete(params) {
return request({
url: '/biz/homeModuleUser/delete',
method: 'post',
params: params
})
}

View File

@@ -11,6 +11,17 @@ export function getHomeUserList(params) {
})
}
/**
* 获取用户信息列表
*/
export function getHomeUserListAll(params) {
return request({
url: '/biz/homeUser/listAll',
method: 'get',
params: params
})
}
/**
* 保存用户信息列表
*/

View File

@@ -9,8 +9,8 @@
<div class="sidebar-content">
<FilterSelect
:list-data="listData"
node-key="groupId"
label-key="groupName"
node-key="moduleId"
label-key="moduleName"
@item-click="handleItemClick"
@edit="handleEdit"
@delete="handleDelete"
@@ -43,8 +43,8 @@ import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
import ResizablePage from '@/components/Table/proResizable.vue'
import FilterSelect from '@/components/Table/proFilterSelect.vue'
import PDialog from '@/components/Dialog/proDialog.vue'
import { getHomeModuleGroupList } from '@/api/bizModule'
import { getHomeModuleList } from '@/api/bizModule'
import { getHomeModuleUserSave , getHomeModuleUserDelete } from '@/api/bizModuleUser'
import vUser from './list.vue'
import vRole from './role.vue'
@@ -61,12 +61,8 @@ const formComponentRef = ref(null)
const getListData = async () => {
try {
const res = await getHomeModuleGroupList({});
console.log(res )
// listData.value = res || []
const res = await getHomeModuleList();
listData.value = res || []
} catch (error) {
console.log(error);
}
@@ -82,7 +78,7 @@ const handleEdit = (item) => {
}
const handleDelete = (item) => {
ElMessageBox.confirm('确定要删除当前角色吗?', '删除确认', {
ElMessageBox.confirm('确定要删除当前模块吗?', '删除确认', {
type: 'warning',
closeOnClickModal: false,
showClose: false
@@ -91,12 +87,12 @@ const handleDelete = (item) => {
const reqParams = {
roleId: item.roleId
}
const res = await getHomeRoleDelete(reqParams);
const res = await getHomeModuleUserDelete(reqParams);
ElMessage.success(res.msg);
getListData();
})
.catch(() => {
ElMessage.info('已取消删除角色操作');
ElMessage.info('已取消删除模块操作');
});
}
@@ -120,16 +116,15 @@ const handleSave = async () => {
if (formComponentRef.value) {
const isValid = await formComponentRef.value.validate()
if (!isValid) {
ElMessage.warning('表单验证失败,请检查必填项');
return
}
const selectedMenuIds = formComponentRef.value.getSelectedMenuIds()
roleForm.value.menuIds = selectedMenuIds
}
const reqParams = {
... roleForm.value
}
saveLoading.value = true
const res = await getHomeRoleAssign(reqParams);
const res = await getHomeModuleUserSave(reqParams);
setTimeout(() => {
ElMessage.success(res.msg)
saveLoading.value = false

View File

@@ -1,246 +1,236 @@
<template>
<div class="role-auth-container">
<el-form
:model="formData"
class="role-info-form"
label-width="80px"
inline
>
<el-form-item label="角色编号:" class="form-col">
<el-input
v-model="formData.roleId"
disabled
class="info-input"
/>
</el-form-item>
<el-form-item label="角色名称:" class="form-col">
<el-input
v-model="formData.roleName"
class="info-input"
/>
</el-form-item>
</el-form>
<div class="menu-tree-wrapper">
<el-form
:model="formData"
:rules="formRules"
ref="formRef"
label-width="100px"
class="dialog-form-container"
>
<div class="form-row">
<div class="form-col">
<el-form-item label="模块编号" prop="moduleId">
<el-input
v-model="formData.moduleId"
placeholder="请输入模块编号"
disabled
clearable
/>
</el-form-item>
</div>
<div class="form-col">
<el-form-item label="模块名称" prop="moduleName">
<el-input
v-model="formData.moduleName"
placeholder="请输入模块名称"
clearable
/>
</el-form-item>
</div>
</div>
<div class="form-row transfer-row">
<div class="form-col transfer-col">
<el-form-item label="权限列表" prop="userIds">
<el-transfer
filterable
v-model="formData.userIds"
:data="transferData"
:props="{ key: 'userId', label: 'uname' }"
:titles="['待选用户', '已选用户']"
placeholder="请输入权限名称搜索"
class="full-width-transfer"
/>
</el-form-item>
</div>
</div>
</div>
</el-form>
</template>
<script setup>
import { ref, reactive, onMounted, defineProps, defineExpose, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { getTreeMenuList } from '@/api/bizMenu'
import { getHomeRoleMenus } from '@/api/bizRole'
import { ref, onMounted, nextTick, watch } from 'vue'
import { ElMessage, ElMessageBox, ElNotification } from 'element-plus'
import { getHomeUserListAll } from '@/api/bizUser'
import { getHomeModuleUserList } from '@/api/bizModuleUser'
const props = defineProps({
formData: {
type: Object,
required: true,
default: () => ({
roleId: '',
roleName: '',
menuIds: []
moduleId: '',
moduleName: '',
userIds: []
})
},
isEdit: {
type: Boolean,
default: false
}
})
const menuTreeData = ref([])
const loading = ref(false)
const menuTreeRef = ref(null)
const selectedMenuIds = ref([])
const formRef = ref(null)
const transferData = ref([])
const getLeafNodeIds = (treeData, leafIds = []) => {
treeData.forEach(node => {
if (!node.children || node.children.length === 0) {
leafIds.push(String(node.id))
} else {
getLeafNodeIds(node.children, leafIds)
}
})
return leafIds
const formRules = {
moduleName: [ { required: true, message: '请输入模块名称', trigger: 'blur' } ],
userIds: [
{ required: true, message: '请至少选择一个用户', trigger: 'change' }
]
}
const filterOnlyLeafIds = (allIds, treeData) => {
const allLeafIds = getLeafNodeIds(treeData)
return allIds.filter(id => allLeafIds.includes(id))
}
const getTreeListData = async () => {
try {
const res = await getTreeMenuList()
menuTreeData.value = res ?? []
return menuTreeData.value
} catch (error) {
console.error('加载菜单树失败:', error)
menuTreeData.value = []
return []
}
}
const getRoleMenuIds = async () => {
try {
const reqParams = { roleId: props.formData.roleId }
const res = await getHomeRoleMenus(reqParams)
return (res ?? []).map(item => String(item?.menuId)).filter(id => id)
} catch (error) {
console.error('加载角色菜单权限失败:', error)
return []
}
}
const treeProps = reactive({
label: 'label',
children: 'children',
disabled: 'disabled'
})
function getIndeterminateKeys(node) {
let keys = []
if (node.indeterminate) {
keys.push(node.key)
}
if (node.childNodes) {
node.childNodes.forEach(c => keys.push(...getIndeterminateKeys(c)))
}
return keys
}
function getCheckedAndIndeterminateKeys() {
if (!menuTreeRef.value) return []
const checked = menuTreeRef.value.getCheckedKeys(false)
const indeterminate = getIndeterminateKeys(menuTreeRef.value.root)
return [...new Set([...checked, ...indeterminate])]
}
onMounted(async () => {
loading.value = true
try {
const treeData = await getTreeListData()
const roleMenuIds = await getRoleMenuIds()
const propsMenuIds = (props.formData?.menuIds ?? []).map(id => String(id)).filter(id => id)
const allMenuIds = roleMenuIds.length > 0 ? roleMenuIds : propsMenuIds
const leafMenuIds = filterOnlyLeafIds(allMenuIds, treeData)
if (leafMenuIds.length > 0) {
selectedMenuIds.value = [...leafMenuIds]
setTimeout(() => {
if (menuTreeRef.value && treeData.length) {
menuTreeRef.value.setCheckedKeys(leafMenuIds, false)
}
}, 300)
}
} catch (error) {
console.error('初始化权限数据失败:', error)
} finally {
loading.value = false
}
})
watch(() => props.formData.menuIds, (newVal) => {
if (!newVal || !newVal.length || !menuTreeRef.value || !menuTreeData.value.length) return
const allMenuIds = newVal.map(id => String(id)).filter(id => id)
const leafMenuIds = filterOnlyLeafIds(allMenuIds, menuTreeData.value)
if (leafMenuIds.length) {
selectedMenuIds.value = [...leafMenuIds]
menuTreeRef.value.setCheckedKeys(leafMenuIds, false)
}
}, { deep: true })
const handleCheck = () => {
if (!menuTreeRef.value) return
selectedMenuIds.value = menuTreeRef.value.getCheckedKeys(false)
}
const handleCheckChange = () => {
handleCheck()
}
const validate = async () => {
if (selectedMenuIds.value.length === 0) {
ElMessage.warning('请至少选择一个菜单权限!')
if (!formRef.value) return false
try {
const valid = await formRef.value.validate()
return valid
} catch (error) {
console.error('表单验证失败:', error)
return false
}
return true
}
const resetForm = () => {
if (menuTreeRef.value) {
menuTreeRef.value.setCheckedKeys([])
selectedMenuIds.value = []
}
if (formRef.value) formRef.value.resetFields()
}
defineExpose({
validate,
resetForm,
getSelectedMenuIds: () => getCheckedAndIndeterminateKeys(),
getLeafMenuIds: () => menuTreeRef.value ? menuTreeRef.value.getCheckedKeys(true) : []
async function getUserData() {
try {
const res = await getHomeUserListAll()
transferData.value = res || []
} catch (error) {
console.error('获取数据失败:', error);
transferData.value = []
}
}
async function getUserModuleData() {
try {
const reqParams = {
moduleId: props.formData.moduleId
}
const res = await getHomeModuleUserList(reqParams)
if (Array.isArray(res)) {
const selectedUserIds = res.map(item => item.userId).filter(Boolean)
nextTick(() => {
props.formData.userIds = selectedUserIds
})
}
} catch (error) {
console.error('获取数据失败:', error);
transUserData.value = []
}
}
watch(() => props.formData.moduleId, () => {
if (props.formData.moduleId) {
getUserModuleData()
}
}, { immediate: true })
onMounted(() => {
getUserData()
getUserModuleData()
})
defineExpose({ validate, resetForm })
</script>
<style scoped>
.role-auth-container {
.dialog-form-container {
width: 100%;
padding: 16px;
margin: 0;
border: 1px solid rgba(64, 158, 255, 0.15);
border-radius: 8px;
box-sizing: border-box;
background: #fff;
}
.role-info-form {
margin-bottom: 16px;
padding-bottom: 12px;
border-bottom: 1px solid #e5e7eb;
width: 100%;
.form-row {
display: flex;
flex-wrap: wrap;
width: 100%;
margin: 0 0 16px 0;
gap: 20px;
}
.form-col {
flex: 1;
min-width: 200px;
}
.info-input {
width: 100%;
}
:deep(.role-info-form .el-form-item) {
margin-bottom: 0;
width: 100%;
}
:deep(.role-info-form .el-input.is-disabled .el-input__inner) {
background-color: #f5f7fa;
color: #666;
.form-row:last-child {
margin-bottom: 0;
}
.menu-tree-wrapper {
width: 100%;
}
.tree-content {
width: 100%;
height: 400px;
overflow-y: auto;
border: 1px solid #e5e7eb;
border-radius: 4px;
padding: 8px;
.form-col {
flex: 1;
min-width: 180px;
box-sizing: border-box;
}
:deep(.el-tree) {
--el-tree-node-content-hover-bg-color: #f5f7fa;
}
:deep(.el-tree-node__content) {
height: 36px;
line-height: 36px;
.transfer-col {
width: 100% !important;
min-width: unset !important;
padding: 0 !important;
margin: 0 !important;
}
.tree-content::-webkit-scrollbar {
width: 6px;
.full-width-transfer {
width: 100% !important;
box-sizing: border-box !important;
padding: 0 !important;
margin: 0 !important;
}
.tree-content::-webkit-scrollbar-thumb {
background-color: #dcdfe6;
border-radius: 3px;
:deep(.el-transfer) {
width: 100% !important;
display: flex !important;
flex-direction: row !important;
flex-wrap: nowrap !important;
align-items: stretch !important;
padding: 0 !important;
margin: 0 !important;
box-sizing: border-box !important;
}
:deep(.el-transfer-panel) {
flex: 1 1 0 !important;
width: calc((100% - 50px) / 2) !important;
max-width: calc((100% - 50px) / 2) !important;
min-width: 150px !important;
padding: 0 !important;
margin: 0 !important;
box-sizing: border-box !important;
}
:deep(.el-transfer__buttons) {
flex: 0 0 50px !important;
display: flex !important;
flex-direction: row !important;
justify-content: center !important;
align-items: center !important;
padding: 0 5px !important;
gap: 5px !important;
height: 100% !important;
margin: auto 0 !important;
}
:deep(.el-transfer__button) {
width: 45px !important;
height: 32px !important;
line-height: 32px !important;
padding: 0 !important;
font-size: 14px !important;
border-radius: 4px !important;
border: 1px solid #dcdfe6 !important;
}
:deep(.el-transfer__button .el-icon) {
display: block !important;
margin: 0 !important;
color: #666 !important;
font-size: 14px !important;
}
:deep(.el-form-item) {
margin: 0 !important;
padding: 0 !important;
}
</style>

View File

@@ -235,7 +235,7 @@ const handleSave = async () => {
if (formComponentRef.value) {
const isValid = await formComponentRef.value.validate()
if (!isValid) {
ElMessage.warning('表单验证失败请检查必填项')
ElMessage.warning('表单验证失败,请检查必填项');
return
}
}

View File

@@ -114,6 +114,7 @@ const handleSave = async () => {
if (formComponentRef.value) {
const isValid = await formComponentRef.value.validate()
if (!isValid) {
ElMessage.warning('表单验证失败,请检查必填项');
return
}
const selectedMenuIds = formComponentRef.value.getSelectedMenuIds()

View File

@@ -266,7 +266,7 @@ const handleSave = async () => {
if (formComponentRef.value) {
const isValid = await formComponentRef.value.validate()
if (!isValid) {
ElMessage.warning('表单验证失败请检查必填项')
ElMessage.warning('表单验证失败,请检查必填项')
return
}
}

View File

@@ -0,0 +1,14 @@
package com.mini.mybigscreen.Model;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
public class ModuleUser implements Serializable {
private String moduleId;
private String moduleName;
private List<String> userIds;
}

View File

@@ -2,10 +2,10 @@ package com.mini.mybigscreen.biz.controller;
import com.mini.mybigscreen.Model.Message;
import com.mini.mybigscreen.Model.Result;
import com.mini.mybigscreen.biz.service.HomeModuleGroupService;
import com.mini.mybigscreen.biz.service.HomeModuleService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -34,7 +34,9 @@ public class HomeModuleController {
}
public Result<Message> delete() {
@PostMapping("delete")
public Result<Message> delete(String moduleId) {
System.out.println(moduleId);
return Result.success(new Message("数据删除成功", 200));
}
}

View File

@@ -1,31 +0,0 @@
package com.mini.mybigscreen.biz.controller;
import com.mini.mybigscreen.Model.Result;
import com.mini.mybigscreen.biz.service.HomeModuleGroupService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 前端控制器
* </p>
*
* @author gaoxq
* @since 2026-03-07
*/
@RestController
@RequestMapping("/biz/homeModuleGroup")
public class HomeModuleGroupController {
@Resource
private HomeModuleGroupService moduleGroupService;
@GetMapping("list")
public Result<?> getList(){
return Result.success(moduleGroupService.list());
}
}

View File

@@ -3,18 +3,18 @@ package com.mini.mybigscreen.biz.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.mini.mybigscreen.Model.Message;
import com.mini.mybigscreen.Model.ModuleUser;
import com.mini.mybigscreen.Model.Result;
import com.mini.mybigscreen.biz.domain.HomeModule;
import com.mini.mybigscreen.biz.domain.HomeModuleUser;
import com.mini.mybigscreen.biz.domain.HomeUser;
import com.mini.mybigscreen.biz.mapper.HomeModuleMapper;
import com.mini.mybigscreen.biz.service.HomeModuleUserService;
import com.mini.mybigscreen.biz.service.HomeUserService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -37,6 +37,9 @@ public class HomeModuleUserController {
@Resource
private HomeModuleMapper homeModuleMapper;
@Resource
private HomeModuleUserService moduleUserService;
@GetMapping("list")
public Result<List<HomeModule>> getList(HttpServletRequest request) {
HttpSession session = request.getSession(false);
@@ -56,12 +59,24 @@ public class HomeModuleUserController {
return Result.success(moduleList);
}
public Result<Message> save() {
return Result.success(new Message("数据新增成功", 200));
/**
* 获取模块已有的用户
*/
@GetMapping("userList")
public Result<?> getUserModuleList(String moduleId) {
LambdaQueryWrapper<HomeModuleUser> ModuleUserQuery = new LambdaQueryWrapper<HomeModuleUser>()
.eq(HomeModuleUser::getModuleId, moduleId);
List<HomeModuleUser> moduleUserList = moduleUserService.list(ModuleUserQuery);
return Result.success(moduleUserList);
}
@PostMapping("save")
public Result<Message> save(@RequestBody ModuleUser moduleUser) {
return Result.success(new Message("数据新增成功", 200));
}
@PostMapping("delete")
public Result<Message> delete() {
return Result.success(new Message("数据删除成功", 200));
}

View File

@@ -32,6 +32,11 @@ public class HomeUserController {
@Resource
private HomeUserService userService;
@GetMapping("listAll")
public Result<?> getListAll() {
return Result.success(userService.list());
}
@GetMapping("list")
public Result<?> getList(Integer pageNum, Integer pageSize,

View File

@@ -1,38 +0,0 @@
package com.mini.mybigscreen.biz.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
*
* </p>
*
* @author gaoxq
* @since 2026-03-07
*/
@Getter
@Setter
@TableName("biz_home_module_group")
public class HomeModuleGroup implements Serializable {
private static final long serialVersionUID = 1L;
@TableField("create_time")
private LocalDateTime createTime;
@TableId(value = "group_id", type = IdType.AUTO)
private String groupId;
@TableField("group_name")
private String groupName;
@TableField("ustatus")
private Integer ustatus;
}

View File

@@ -4,9 +4,8 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;
import com.mini.mybigscreen.Model.BaseEntity;
import lombok.Getter;
@@ -14,22 +13,24 @@ import lombok.Setter;
/**
* <p>
*
*
* </p>
*
* @author gaoxq
* @since 2026-02-28
* @since 2026-03-07
*/
@Getter
@Setter
@TableName("biz_home_user")
public class HomeUser extends BaseEntity implements Serializable {
public class HomeUser extends BaseEntity implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
/**
* 记录日期
*/
@TableField("create_time")
private String createTime;
private LocalDateTime createTime;
@TableId(value = "user_id", type = IdType.AUTO)
private String userId;
@@ -47,7 +48,7 @@ public class HomeUser extends BaseEntity implements Serializable {
* 性别
*/
@TableField("sex")
private String sex;
private Integer sex;
/**
* 电子邮件
@@ -67,12 +68,6 @@ public class HomeUser extends BaseEntity implements Serializable {
@TableField("role_id")
private String roleId;
/**
* 模块名称
*/
@TableField("group_module_id")
private String groupModuleId;
/**
* 用户状态
*/
@@ -90,4 +85,25 @@ public class HomeUser extends BaseEntity implements Serializable {
*/
@TableField("last_login_ip")
private String lastLoginIp;
@TableField("f_tenant_id")
private String fTenantId;
/**
* 流程id
*/
@TableField("f_flow_id")
private String fFlowId;
/**
* 流程任务主键
*/
@TableField("f_flow_task_id")
private String fFlowTaskId;
/**
* 流程任务状态
*/
@TableField("f_flow_state")
private Integer fFlowState;
}

View File

@@ -1,16 +0,0 @@
package com.mini.mybigscreen.biz.mapper;
import com.github.yulichang.base.MPJBaseMapper;
import com.mini.mybigscreen.biz.domain.HomeModuleGroup;
/**
* <p>
* Mapper 接口
* </p>
*
* @author gaoxq
* @since 2026-03-07
*/
public interface HomeModuleGroupMapper extends MPJBaseMapper<HomeModuleGroup> {
}

View File

@@ -2,14 +2,13 @@ package com.mini.mybigscreen.biz.mapper;
import com.github.yulichang.base.MPJBaseMapper;
import com.mini.mybigscreen.biz.domain.HomeUser;
/**
* <p>
* Mapper 接口
* </p>
*
* @author gaoxq
* @since 2026-02-28
* @since 2026-03-07
*/
public interface HomeUserMapper extends MPJBaseMapper<HomeUser> {

View File

@@ -1,16 +0,0 @@
package com.mini.mybigscreen.biz.service;
import com.mini.mybigscreen.biz.domain.HomeModuleGroup;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author gaoxq
* @since 2026-03-07
*/
public interface HomeModuleGroupService extends IService<HomeModuleGroup> {
}

View File

@@ -1,20 +0,0 @@
package com.mini.mybigscreen.biz.service.impl;
import com.mini.mybigscreen.biz.domain.HomeModuleGroup;
import com.mini.mybigscreen.biz.mapper.HomeModuleGroupMapper;
import com.mini.mybigscreen.biz.service.HomeModuleGroupService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author gaoxq
* @since 2026-03-07
*/
@Service
public class HomeModuleGroupServiceImpl extends ServiceImpl<HomeModuleGroupMapper, HomeModuleGroup> implements HomeModuleGroupService {
}