大屏项目初始化

This commit is contained in:
2026-03-07 12:13:00 +08:00
parent d887108e1a
commit b7bfdfd2bc
9 changed files with 222 additions and 71 deletions

View File

@@ -33,6 +33,17 @@ export function getHomeRoleAssign(data) {
})
}
/**
* 保存角色信息列表
*/
export function getHomeRoleSave(data) {
return request({
url: '/biz/homeRole/save',
method: 'post',
data
})
}
/**
* 删除角色信息

View File

@@ -191,7 +191,10 @@ const openedSubMenuKeys = ref([])
const getMenuList = async () => {
if (!isMounted.value) return
try {
const res = await getUserMenuList();
const reqParams = {
roleId: userStore.loginUser.roleId,
}
const res = await getUserMenuList(reqParams);
menuList.value = res || [];
const setMenuNameMap = (menus) => {
menus.forEach(menu => {

View File

@@ -1,8 +1,99 @@
<template>
<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="roleName">
<el-input
v-model="formData.roleName"
placeholder="请输入角色名称"
clearable
:disabled="isEdit"
/>
</el-form-item>
</div>
<div class="form-col">
<el-form-item label="角色状态" prop="ustatus">
<el-select
v-model="formData.ustatus"
placeholder="请选择角色状态"
clearable
>
<el-option label="停用" value="0" />
<el-option label="在用" value="1" />
<el-option label="锁定" value="2" />
</el-select>
</el-form-item>
</div>
</div>
</el-form>
</template>
<script>
<script setup>
import { ref, onMounted } from 'vue'
const props = defineProps({
formData: {
type: Object,
required: true,
default: () => ({
roleName: '',
ustatus: '1',
})
},
isEdit: {
type: Boolean,
default: false
}
})
const formRef = ref(null)
const formRules = {
roleName: [ { required: true, message: '请输入角色名称', trigger: 'blur' } ],
ustatus: [ { required: true, message: '请选择角色状态', trigger: 'change' } ],
}
const validate = async () => {
if (!formRef.value) return false
try {
const valid = await formRef.value.validate()
return valid
} catch (error) {
console.error('表单验证失败:', error)
return false
}
}
const resetForm = () => {
if (formRef.value) formRef.value.resetFields()
}
defineExpose({ validate, resetForm })
</script>
<style>
<style scoped>
.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;
}
.form-row {
display: flex;
flex-wrap: wrap;
width: 100%;
margin: 0 0 16px 0;
gap: 20px;
}
.form-row:last-child { margin-bottom: 0; }
.form-col { flex: 1; min-width: 180px; }
</style>

View File

@@ -20,7 +20,7 @@
</template>
<template #main>
<div class="main-content">
<vUser />
<vUser @refresh-role-list="getListData" />
</div>
</template>
</ResizablePage>

View File

@@ -67,18 +67,6 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="260" align="center" fixed="right">
<template #default="scope">
<el-button size="small" type="primary" @click="handleEdit(scope.row)">
<el-icon><Edit /></el-icon>
编辑
</el-button>
<el-button size="small" type="danger" @click="handleDelete(scope.row)">
<el-icon><Delete /></el-icon>
删除
</el-button>
</template>
</el-table-column>
</template>
</STable>
</div>
@@ -86,6 +74,7 @@
<PDialog
v-model="dialogVisible"
:loading="saveLoading"
:title="isEdit ? '编辑数据' : '新增数据'"
@close="handleDialogClose"
@reset="handleDialogReset"
@@ -101,6 +90,7 @@ import { ref, reactive, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { Plus, Download, Edit, Delete } from '@element-plus/icons-vue'
import { getHomeUserList } from '@/api/bizUser'
import { getHomeRoleSave } from '@/api/bizRole'
import CSearch from '@/components/Search/proSearch.vue'
import STable from '@/components/Table/proTable.vue'
@@ -108,8 +98,10 @@ import PDialog from '@/components/Dialog/proDialog.vue'
import VForm from './form.vue'
const formComponentRef = ref(null)
const emit = defineEmits(['refresh-role-list'])
const loading = ref(false)
const saveLoading = ref(false)
const searchForm = reactive({
uname: '',
ustatus: '',
@@ -187,10 +179,6 @@ const handleExport = () => {
ElMessage.success('开始导出数据...')
}
const handleDelete = (row) => {
ElMessage.warning(`删除ID为 ${row.id} 的数据`)
}
const handleSizeChange = (val) => {
pagination.pageSize = val
getDataList()
@@ -222,12 +210,21 @@ const handleSave = async () => {
return
}
}
setTimeout(() => {
ElMessage.success(isEdit.value ? '编辑成功' : '新增成功')
dialogVisible.value = false
getDataList()
}, 500)
try {
saveLoading.value = true;
const reqParams = {
...formData.value
}
const res = await getHomeRoleSave(reqParams);
ElMessage.success(res.msg)
dialogVisible.value = false
emit('refresh-role-list')
} catch (error) {
console.error('获取数据失败:', error);
} finally {
saveLoading.value = false;
}
}
onMounted(() => {

View File

@@ -63,13 +63,31 @@ const loading = ref(false)
const menuTreeRef = ref(null)
const selectedMenuIds = 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 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 []
}
}
@@ -90,21 +108,38 @@ const treeProps = reactive({
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 [_, roleMenuIds] = await Promise.all([
getTreeListData(),
getRoleMenuIds()
])
const treeData = await getTreeListData()
const roleMenuIds = await getRoleMenuIds()
const propsMenuIds = (props.formData?.menuIds ?? []).map(id => String(id)).filter(id => id)
const defaultCheckedIds = roleMenuIds.length > 0 ? roleMenuIds : propsMenuIds
if (defaultCheckedIds.length > 0) {
selectedMenuIds.value = [...defaultCheckedIds]
const allMenuIds = roleMenuIds.length > 0 ? roleMenuIds : propsMenuIds
const leafMenuIds = filterOnlyLeafIds(allMenuIds, treeData)
if (leafMenuIds.length > 0) {
selectedMenuIds.value = [...leafMenuIds]
setTimeout(() => {
if (menuTreeRef.value && menuTreeData.value.length) {
menuTreeRef.value.setCheckedKeys(defaultCheckedIds, false)
if (menuTreeRef.value && treeData.length) {
menuTreeRef.value.setCheckedKeys(leafMenuIds, false)
}
}, 300)
}
@@ -116,12 +151,14 @@ onMounted(async () => {
})
watch(() => props.formData.menuIds, (newVal) => {
if (!newVal || !newVal.length || !menuTreeRef.value) return
if (!newVal || !newVal.length || !menuTreeRef.value || !menuTreeData.value.length) return
const menuIds = newVal.map(id => String(id)).filter(id => id)
if (menuIds.length) {
selectedMenuIds.value = [...menuIds]
menuTreeRef.value.setCheckedKeys(menuIds, false)
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 })
@@ -130,7 +167,7 @@ const handleCheck = () => {
selectedMenuIds.value = menuTreeRef.value.getCheckedKeys(false)
}
const handleCheckChange = (data, checked, indeterminate) => {
const handleCheckChange = () => {
handleCheck()
}
@@ -152,7 +189,7 @@ const resetForm = () => {
defineExpose({
validate,
resetForm,
getSelectedMenuIds: () => selectedMenuIds.value,
getSelectedMenuIds: () => getCheckedAndIndeterminateKeys(),
getLeafMenuIds: () => menuTreeRef.value ? menuTreeRef.value.getCheckedKeys(true) : []
})
</script>

View File

@@ -138,12 +138,12 @@ const dialogVisible = ref(false)
async function getDataList() {
loading.value = true
try {
const reqParmas = {
const reqParams = {
... searchForm,
pageNum: pagination.pageNum,
pageSize: pagination.pageSize,
}
const res = await getHomeUserList(reqParmas);
const res = await getHomeUserList(reqParams);
pagination.total = res.total;
tableData.value = res.list || [];
} catch (error) {