大屏项目初始化
This commit is contained in:
12
screen-vue/src/api/bizModule.js
Normal file
12
screen-vue/src/api/bizModule.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取指标信息列表
|
||||||
|
*/
|
||||||
|
export function getHomeModuleList(params) {
|
||||||
|
return request({
|
||||||
|
url: '/biz/homeModule/list',
|
||||||
|
method: 'get',
|
||||||
|
params: params
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -325,9 +325,10 @@ const handleFullScreen = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleBigScreen = () => {
|
const handleBigScreen = () => {
|
||||||
if (!isMounted.value) return
|
const { href } = router.resolve({
|
||||||
const baseUrl = window.location.origin + "/#/bigScreen";
|
path: "/bigScreen"
|
||||||
window.open(baseUrl, '_blank');
|
});
|
||||||
|
window.open(href, '_blank');
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleCommand = (cmd) => {
|
const handleCommand = (cmd) => {
|
||||||
|
|||||||
@@ -3,10 +3,46 @@ import Login from '@/views/Login.vue'
|
|||||||
import Page404 from '@/views/error/404.vue'
|
import Page404 from '@/views/error/404.vue'
|
||||||
import Layout from '@/components/Layout/index.vue'
|
import Layout from '@/components/Layout/index.vue'
|
||||||
import Dashboard from '@/views/desktop/index.vue'
|
import Dashboard from '@/views/desktop/index.vue'
|
||||||
import bigScreen from '@/views/screen/index.vue'
|
import BigScreen from '@/views/screen/index.vue'
|
||||||
|
import BigScreenWork from '@/views/screen/Work/index.vue'
|
||||||
import { useUserStore } from '@/stores/user'
|
import { useUserStore } from '@/stores/user'
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
|
|
||||||
|
const bigScreenModules = import.meta.glob('../views/screen/**/{index,list}.vue', {
|
||||||
|
eager: false,
|
||||||
|
import: 'default'
|
||||||
|
})
|
||||||
|
|
||||||
|
const generateBigScreenRoutes = () => {
|
||||||
|
const routes = []
|
||||||
|
|
||||||
|
Object.entries(bigScreenModules).forEach(([filePath, module]) => {
|
||||||
|
if (filePath === '../views/screen/index.vue') return;
|
||||||
|
|
||||||
|
const routePath = filePath
|
||||||
|
.replace('../views', '')
|
||||||
|
.replace('.vue', '')
|
||||||
|
.toLowerCase();
|
||||||
|
|
||||||
|
const finalPath = routePath;
|
||||||
|
const routeName = finalPath
|
||||||
|
.split('/')
|
||||||
|
.filter(Boolean)
|
||||||
|
.map(seg => seg.charAt(0).toUpperCase() + seg.slice(1))
|
||||||
|
.join('')
|
||||||
|
|| 'SystemRoleIndex';
|
||||||
|
|
||||||
|
routes.push({
|
||||||
|
path: finalPath,
|
||||||
|
name: routeName,
|
||||||
|
component: module,
|
||||||
|
meta: { requiresAuth: true }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return routes
|
||||||
|
}
|
||||||
|
|
||||||
const modules = import.meta.glob('../views/**/{index,list}.vue', {
|
const modules = import.meta.glob('../views/**/{index,list}.vue', {
|
||||||
eager: false,
|
eager: false,
|
||||||
import: 'default'
|
import: 'default'
|
||||||
@@ -18,10 +54,10 @@ const generateRoutes = () => {
|
|||||||
Object.entries(modules).forEach(([filePath, module]) => {
|
Object.entries(modules).forEach(([filePath, module]) => {
|
||||||
const excludePaths = [
|
const excludePaths = [
|
||||||
'views/Login.vue',
|
'views/Login.vue',
|
||||||
'views/desktop/index.vue',
|
'views/desktop/index.vue',
|
||||||
'views/error/',
|
'views/error/',
|
||||||
'views/screen/',
|
'views/screen/',
|
||||||
]
|
]
|
||||||
if (excludePaths.some(path => filePath.includes(path))) {
|
if (excludePaths.some(path => filePath.includes(path))) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -40,7 +76,8 @@ const generateRoutes = () => {
|
|||||||
routes.push({
|
routes.push({
|
||||||
path: routePath,
|
path: routePath,
|
||||||
name: routeName || 'SystemRoleIndex',
|
name: routeName || 'SystemRoleIndex',
|
||||||
component: module
|
component: module,
|
||||||
|
meta: { requiresAuth: true }
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -56,9 +93,22 @@ const routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/bigScreen',
|
path: '/bigScreen',
|
||||||
name: 'bigScreen',
|
name: 'BigScreen',
|
||||||
component: bigScreen,
|
component: BigScreen,
|
||||||
meta: { requiresAuth: true }
|
meta: { requiresAuth: true },
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/bigScreenWork',
|
||||||
|
name: 'BigScreenWork',
|
||||||
|
component: BigScreenWork
|
||||||
|
},
|
||||||
|
...generateBigScreenRoutes(),
|
||||||
|
{
|
||||||
|
path: '/:pathMatch(.*)*',
|
||||||
|
name: 'BigScreen404',
|
||||||
|
component: Page404
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
|
|||||||
147
screen-vue/src/views/database/screen/form.vue
Normal file
147
screen-vue/src/views/database/screen/form.vue
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
<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="moduleName">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.moduleName"
|
||||||
|
placeholder="请输入模块名称"
|
||||||
|
clearable
|
||||||
|
:disabled="isEdit"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
<div class="form-col">
|
||||||
|
<el-form-item label="模块编码" prop="moduleCode">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.moduleCode"
|
||||||
|
placeholder="请输入模块编码"
|
||||||
|
clearable
|
||||||
|
:disabled="isEdit"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-col">
|
||||||
|
<el-form-item label="大屏标题" prop="titleName">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.titleName"
|
||||||
|
placeholder="请输入大屏标题"
|
||||||
|
clearable
|
||||||
|
:disabled="isEdit"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
<div class="form-col">
|
||||||
|
<el-form-item label="路由地址" prop="path">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.path"
|
||||||
|
placeholder="请输入路由地址"
|
||||||
|
clearable
|
||||||
|
:disabled="isEdit"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-col">
|
||||||
|
<el-form-item label="模块描述" prop="remark">
|
||||||
|
<el-input
|
||||||
|
v-model="formData.remark"
|
||||||
|
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 setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
formData: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
default: () => ({
|
||||||
|
moduleName: '',
|
||||||
|
ustatus: '1',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
isEdit: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const formRef = ref(null)
|
||||||
|
|
||||||
|
const formRules = {
|
||||||
|
moduleName: [ { 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 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>
|
||||||
156
screen-vue/src/views/database/screen/index.vue
Normal file
156
screen-vue/src/views/database/screen/index.vue
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
<template>
|
||||||
|
<ResizablePage
|
||||||
|
:defaultWidth="200"
|
||||||
|
:minWidth="150"
|
||||||
|
:maxWidth="420"
|
||||||
|
bgColor="#fff"
|
||||||
|
>
|
||||||
|
<template #sidebar>
|
||||||
|
<div class="sidebar-content">
|
||||||
|
<FilterSelect
|
||||||
|
:list-data="listData"
|
||||||
|
node-key="groupId"
|
||||||
|
label-key="groupName"
|
||||||
|
@item-click="handleItemClick"
|
||||||
|
@edit="handleEdit"
|
||||||
|
@delete="handleDelete"
|
||||||
|
@view="handleView"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #main>
|
||||||
|
<div class="main-content">
|
||||||
|
<vUser @refresh-role-list="getListData" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</ResizablePage>
|
||||||
|
|
||||||
|
<PDialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
title="模块授权"
|
||||||
|
:loading="saveLoading"
|
||||||
|
@close="handleDialogClose"
|
||||||
|
@reset="handleDialogReset"
|
||||||
|
@confirm="handleSave"
|
||||||
|
>
|
||||||
|
<vRole ref="formComponentRef" :form-data="roleForm" />
|
||||||
|
</PDialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
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 vUser from './list.vue'
|
||||||
|
import vRole from './role.vue'
|
||||||
|
|
||||||
|
const FormValues = ref({
|
||||||
|
menuId: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const listData = ref([]);
|
||||||
|
const saveLoading = ref(false)
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const roleForm = ref({})
|
||||||
|
const formComponentRef = ref(null)
|
||||||
|
|
||||||
|
const getListData = async () => {
|
||||||
|
try {
|
||||||
|
const res = await getHomeModuleGroupList({});
|
||||||
|
|
||||||
|
|
||||||
|
console.log(res )
|
||||||
|
|
||||||
|
// listData.value = res || []
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleItemClick = (item) => {
|
||||||
|
console.log('选中了:', item)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEdit = (item) => {
|
||||||
|
roleForm.value = { ...item }
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDelete = (item) => {
|
||||||
|
ElMessageBox.confirm('确定要删除当前角色吗?', '删除确认', {
|
||||||
|
type: 'warning',
|
||||||
|
closeOnClickModal: false,
|
||||||
|
showClose: false
|
||||||
|
})
|
||||||
|
.then(async () => {
|
||||||
|
const reqParams = {
|
||||||
|
roleId: item.roleId
|
||||||
|
}
|
||||||
|
const res = await getHomeRoleDelete(reqParams);
|
||||||
|
ElMessage.success(res.msg);
|
||||||
|
getListData();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
ElMessage.info('已取消删除角色操作');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleView = (item) => {
|
||||||
|
console.log('查看', item)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDialogClose = () => {
|
||||||
|
roleForm.value = {}
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDialogReset = () => {
|
||||||
|
if (formComponentRef.value) {
|
||||||
|
formComponentRef.value.resetForm()
|
||||||
|
ElMessage.info('表单已重置')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
if (formComponentRef.value) {
|
||||||
|
const isValid = await formComponentRef.value.validate()
|
||||||
|
if (!isValid) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const selectedMenuIds = formComponentRef.value.getSelectedMenuIds()
|
||||||
|
roleForm.value.menuIds = selectedMenuIds
|
||||||
|
}
|
||||||
|
const reqParams = {
|
||||||
|
... roleForm.value
|
||||||
|
}
|
||||||
|
saveLoading.value = true
|
||||||
|
const res = await getHomeRoleAssign(reqParams);
|
||||||
|
setTimeout(() => {
|
||||||
|
ElMessage.success(res.msg)
|
||||||
|
saveLoading.value = false
|
||||||
|
dialogVisible.value = false
|
||||||
|
getListData()
|
||||||
|
}, 500)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getListData();
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.sidebar-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
padding: 0px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
277
screen-vue/src/views/database/screen/list.vue
Normal file
277
screen-vue/src/views/database/screen/list.vue
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
<template>
|
||||||
|
<div class="data-manage-page">
|
||||||
|
<CSearch
|
||||||
|
@search="handleSearch"
|
||||||
|
@reset="handleReset"
|
||||||
|
>
|
||||||
|
<el-form-item label="用户名称:" class="search-item">
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.uname"
|
||||||
|
placeholder="请输入用户名称"
|
||||||
|
clearable
|
||||||
|
class="search-input"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="登录账户:" class="search-item">
|
||||||
|
<el-input
|
||||||
|
v-model="searchForm.userName"
|
||||||
|
placeholder="请输入登录账户"
|
||||||
|
clearable
|
||||||
|
class="search-input"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用户状态:" class="search-item">
|
||||||
|
<el-select
|
||||||
|
v-model="searchForm.ustatus"
|
||||||
|
placeholder="请选择用户状态"
|
||||||
|
clearable
|
||||||
|
class="search-select"
|
||||||
|
>
|
||||||
|
<el-option label="停用" value="0" />
|
||||||
|
<el-option label="在用" value="1" />
|
||||||
|
<el-option label="锁定" value="2" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</CSearch>
|
||||||
|
|
||||||
|
<div class="main-wrapper">
|
||||||
|
<div class="main-section">
|
||||||
|
<div class="action-section">
|
||||||
|
<el-button type="primary" icon="Plus" @click="handleAdd">
|
||||||
|
新增
|
||||||
|
</el-button>
|
||||||
|
<el-button type="success" icon="Download" @click="handleExport">
|
||||||
|
导出
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<STable
|
||||||
|
:table-data="tableData"
|
||||||
|
:loading="loading"
|
||||||
|
:pagination="pagination"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
>
|
||||||
|
<template #columns>
|
||||||
|
<el-table-column prop="createTime" label="记录日期" width="180" fixed="left" />
|
||||||
|
<el-table-column prop="userName" label="登录账户" />
|
||||||
|
<el-table-column prop="uname" label="用户名称" />
|
||||||
|
<el-table-column prop="sex" label="性别" />
|
||||||
|
<el-table-column prop="email" label="电子邮箱" width="225" show-overflow-tooltip="true" />
|
||||||
|
<el-table-column prop="phone" label="联系电话" />
|
||||||
|
<el-table-column prop="ustatus" label="状态" min-width="100" align="center">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-tag
|
||||||
|
:type="scope.row.ustatus === '1' ? 'success' : scope.row.ustatus === '2' ? 'warning' : 'danger'"
|
||||||
|
>
|
||||||
|
{{ getStatusText(scope.row.ustatus) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
</STable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<PDialog
|
||||||
|
v-model="dialogVisible"
|
||||||
|
:loading="saveLoading"
|
||||||
|
:title="isEdit ? '编辑数据' : '新增数据'"
|
||||||
|
@close="handleDialogClose"
|
||||||
|
@reset="handleDialogReset"
|
||||||
|
@confirm="handleSave"
|
||||||
|
>
|
||||||
|
<VForm ref="formComponentRef" :form-data="formData" :is-edit="isEdit" />
|
||||||
|
</PDialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
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'
|
||||||
|
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: '',
|
||||||
|
userName: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const pagination = reactive({
|
||||||
|
pageNum: 1,
|
||||||
|
pageSize: 20,
|
||||||
|
total: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
const tableData = ref([])
|
||||||
|
|
||||||
|
const dialogVisible = ref(false)
|
||||||
|
const isEdit = ref(false)
|
||||||
|
const formData = ref({})
|
||||||
|
|
||||||
|
async function getDataList() {
|
||||||
|
loading.value = true
|
||||||
|
try {
|
||||||
|
const reqParmas = {
|
||||||
|
... searchForm,
|
||||||
|
pageNum: pagination.pageNum,
|
||||||
|
pageSize: pagination.pageSize,
|
||||||
|
}
|
||||||
|
const res = await getHomeUserList(reqParmas);
|
||||||
|
pagination.total = res.total;
|
||||||
|
tableData.value = res.list || [];
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取数据失败:', error);
|
||||||
|
tableData.value = []
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatusText = (status) => {
|
||||||
|
const statusMap = {
|
||||||
|
'0': '停用',
|
||||||
|
'1': '在用',
|
||||||
|
'2': '锁定'
|
||||||
|
}
|
||||||
|
return statusMap[status] || '未知'
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSearch = () => {
|
||||||
|
pagination.pageNum = 1
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleReset = () => {
|
||||||
|
Object.assign(searchForm, {
|
||||||
|
uname: '',
|
||||||
|
ustatus: '',
|
||||||
|
userName: ''
|
||||||
|
})
|
||||||
|
pagination.pageNum = 1
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleAdd = () => {
|
||||||
|
isEdit.value = false
|
||||||
|
formData.value = {}
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEdit = (row) => {
|
||||||
|
isEdit.value = true
|
||||||
|
formData.value = { ...row }
|
||||||
|
dialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleExport = () => {
|
||||||
|
ElMessage.success('开始导出数据...')
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSizeChange = (val) => {
|
||||||
|
pagination.pageSize = val
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCurrentChange = (val) => {
|
||||||
|
pagination.pageNum = val
|
||||||
|
getDataList()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDialogClose = () => {
|
||||||
|
formData.value = {}
|
||||||
|
isEdit.value = false
|
||||||
|
dialogVisible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDialogReset = () => {
|
||||||
|
if (formComponentRef.value) {
|
||||||
|
formComponentRef.value.resetForm()
|
||||||
|
ElMessage.info('表单已重置')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
if (formComponentRef.value) {
|
||||||
|
const isValid = await formComponentRef.value.validate()
|
||||||
|
if (!isValid) {
|
||||||
|
ElMessage.warning('表单验证失败,请检查必填项')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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(() => {
|
||||||
|
getDataList()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.data-manage-page {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 4px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-wrapper {
|
||||||
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 0;
|
||||||
|
border: 1px solid #e5e7eb;
|
||||||
|
border-radius: 6px;
|
||||||
|
margin: 0 !important;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-section {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-section {
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-bottom: 1px solid #e5e7eb;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-button .el-icon) {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
246
screen-vue/src/views/database/screen/role.vue
Normal file
246
screen-vue/src/views/database/screen/role.vue
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
<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">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</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'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
formData: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
default: () => ({
|
||||||
|
roleId: '',
|
||||||
|
roleName: '',
|
||||||
|
menuIds: []
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const menuTreeData = ref([])
|
||||||
|
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 []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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('请至少选择一个菜单权限!')
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
if (menuTreeRef.value) {
|
||||||
|
menuTreeRef.value.setCheckedKeys([])
|
||||||
|
selectedMenuIds.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
validate,
|
||||||
|
resetForm,
|
||||||
|
getSelectedMenuIds: () => getCheckedAndIndeterminateKeys(),
|
||||||
|
getLeafMenuIds: () => menuTreeRef.value ? menuTreeRef.value.getCheckedKeys(true) : []
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.role-auth-container {
|
||||||
|
width: 100%;
|
||||||
|
padding: 16px;
|
||||||
|
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%;
|
||||||
|
display: flex;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-tree-wrapper {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-content {
|
||||||
|
width: 100%;
|
||||||
|
height: 400px;
|
||||||
|
overflow-y: auto;
|
||||||
|
border: 1px solid #e5e7eb;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 8px;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tree-content::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
.tree-content::-webkit-scrollbar-thumb {
|
||||||
|
background-color: #dcdfe6;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -9,17 +9,17 @@
|
|||||||
<div class="erp-section erp-upper-section">
|
<div class="erp-section erp-upper-section">
|
||||||
<div class="erp-col erp-col-1-3">
|
<div class="erp-col erp-col-1-3">
|
||||||
<div class="erp-card">
|
<div class="erp-card">
|
||||||
<ChartV01 :formParams="props.formParams" />
|
<ChartV01 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="erp-col erp-col-1-3">
|
<div class="erp-col erp-col-1-3">
|
||||||
<div class="erp-card">
|
<div class="erp-card">
|
||||||
<ChartV02 :formParams="props.formParams" />
|
<ChartV02 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="erp-col erp-col-1-3">
|
<div class="erp-col erp-col-1-3">
|
||||||
<div class="erp-card">
|
<div class="erp-card">
|
||||||
<ChartV03 :formParams="props.formParams" />
|
<ChartV03 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -29,19 +29,19 @@
|
|||||||
<div class="erp-inner-layout">
|
<div class="erp-inner-layout">
|
||||||
<div class="erp-col erp-col-1-2">
|
<div class="erp-col erp-col-1-2">
|
||||||
<div class="erp-card">
|
<div class="erp-card">
|
||||||
<ChartV04 :formParams="props.formParams" />
|
<ChartV04 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="erp-col erp-col-1-2">
|
<div class="erp-col erp-col-1-2">
|
||||||
<div class="erp-card">
|
<div class="erp-card">
|
||||||
<ChartV05 :formParams="props.formParams" />
|
<ChartV05 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="erp-col erp-col-1-2">
|
<div class="erp-col erp-col-1-2">
|
||||||
<div class="erp-card">
|
<div class="erp-card">
|
||||||
<ChartV06 :formParams="props.formParams" />
|
<ChartV06 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -51,19 +51,19 @@
|
|||||||
<div class="erp-inner-layout">
|
<div class="erp-inner-layout">
|
||||||
<div class="erp-col erp-col-1-2">
|
<div class="erp-col erp-col-1-2">
|
||||||
<div class="erp-card">
|
<div class="erp-card">
|
||||||
<ChartV07 :formParams="props.formParams" />
|
<ChartV07 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="erp-col erp-col-1-2">
|
<div class="erp-col erp-col-1-2">
|
||||||
<div class="erp-card">
|
<div class="erp-card">
|
||||||
<ChartV08 :formParams="props.formParams" />
|
<ChartV08 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="erp-col erp-col-1-2">
|
<div class="erp-col erp-col-1-2">
|
||||||
<div class="erp-card">
|
<div class="erp-card">
|
||||||
<ChartV09 :formParams="props.formParams" />
|
<ChartV09 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -72,6 +72,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
import ChartTop from './components/ChartTop.vue'
|
import ChartTop from './components/ChartTop.vue'
|
||||||
import ChartV01 from './components/ChartV01.vue';
|
import ChartV01 from './components/ChartV01.vue';
|
||||||
import ChartV02 from './components/ChartV02.vue';
|
import ChartV02 from './components/ChartV02.vue';
|
||||||
@@ -83,15 +84,17 @@ import ChartV07 from './components/ChartV07.vue';
|
|||||||
import ChartV08 from './components/ChartV08.vue';
|
import ChartV08 from './components/ChartV08.vue';
|
||||||
import ChartV09 from './components/ChartV09.vue';
|
import ChartV09 from './components/ChartV09.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const route = useRoute();
|
||||||
formParams: {
|
|
||||||
type: Object,
|
const FormValues = ref({
|
||||||
default: () => ({})
|
reqParam: route.query.year
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.formParams,
|
() => route.query.year,
|
||||||
|
(newVal) => {
|
||||||
|
FormValues.value.reqParam = newVal;
|
||||||
|
},
|
||||||
{
|
{
|
||||||
deep: true,
|
deep: true,
|
||||||
immediate: true
|
immediate: true
|
||||||
|
|||||||
8
screen-vue/src/views/screen/Home/index.vue
Normal file
8
screen-vue/src/views/screen/Home/index.vue
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
</style>
|
||||||
@@ -9,34 +9,34 @@
|
|||||||
<div class="work-section work-main-section">
|
<div class="work-section work-main-section">
|
||||||
<div class="work-col work-col-1-3 work-left-col">
|
<div class="work-col work-col-1-3 work-left-col">
|
||||||
<div class="work-card work-card-1-3">
|
<div class="work-card work-card-1-3">
|
||||||
<ChartV01 :formParams="props.formParams" />
|
<ChartV01 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
<div class="work-card work-card-1-3">
|
<div class="work-card work-card-1-3">
|
||||||
<ChartV02 :formParams="props.formParams" />
|
<ChartV02 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
<div class="work-card work-card-1-3">
|
<div class="work-card work-card-1-3">
|
||||||
<ChartV03 :formParams="props.formParams" />
|
<ChartV03 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="work-col work-col-1-3 work-middle-col">
|
<div class="work-col work-col-1-3 work-middle-col">
|
||||||
<div class="work-card work-card-2-3">
|
<div class="work-card work-card-2-3">
|
||||||
<ChartV04 :formParams="props.formParams" />
|
<ChartV04 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
<div class="work-card work-card-1-3">
|
<div class="work-card work-card-1-3">
|
||||||
<ChartV05 :formParams="props.formParams" />
|
<ChartV05 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="work-col work-col-1-3 work-right-col">
|
<div class="work-col work-col-1-3 work-right-col">
|
||||||
<div class="work-card work-card-1-3">
|
<div class="work-card work-card-1-3">
|
||||||
<ChartV06 :formParams="props.formParams" />
|
<ChartV06 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
<div class="work-card work-card-1-3">
|
<div class="work-card work-card-1-3">
|
||||||
<ChartV07 :formParams="props.formParams" />
|
<ChartV07 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
<div class="work-card work-card-1-3">
|
<div class="work-card work-card-1-3">
|
||||||
<ChartV08 :formParams="props.formParams" />
|
<ChartV08 :formParams="FormValues" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -45,6 +45,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
import ChartTop from './components/ChartTop.vue'
|
import ChartTop from './components/ChartTop.vue'
|
||||||
import ChartV01 from './components/ChartV01.vue';
|
import ChartV01 from './components/ChartV01.vue';
|
||||||
import ChartV02 from './components/ChartV02.vue';
|
import ChartV02 from './components/ChartV02.vue';
|
||||||
@@ -55,16 +56,17 @@ import ChartV06 from './components/ChartV06.vue';
|
|||||||
import ChartV07 from './components/ChartV07.vue';
|
import ChartV07 from './components/ChartV07.vue';
|
||||||
import ChartV08 from './components/ChartV08.vue';
|
import ChartV08 from './components/ChartV08.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const route = useRoute();
|
||||||
formParams: {
|
|
||||||
type: Object,
|
const FormValues = ref({
|
||||||
default: () => ({})
|
reqParam: route.query.year
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.formParams,
|
() => route.query.year,
|
||||||
(newVal) => {},
|
(newVal) => {
|
||||||
|
FormValues.value.reqParam = newVal;
|
||||||
|
},
|
||||||
{
|
{
|
||||||
deep: true,
|
deep: true,
|
||||||
immediate: true
|
immediate: true
|
||||||
|
|||||||
@@ -8,12 +8,19 @@
|
|||||||
<div class="tabs-left">
|
<div class="tabs-left">
|
||||||
<div
|
<div
|
||||||
class="tab-item"
|
class="tab-item"
|
||||||
v-for="tab in allTabs"
|
:class="{ active: isHome }"
|
||||||
:key="tab.moduleCode"
|
@click="goHome"
|
||||||
:class="{ active: activeTab === tab.moduleCode }"
|
|
||||||
@click="switchTab(tab.moduleCode)"
|
|
||||||
>
|
>
|
||||||
<span>{{ tab.moduleName }}</span>
|
<span>首页</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="tab-item"
|
||||||
|
v-for="item in allTabs"
|
||||||
|
:key="item.moduleCode"
|
||||||
|
:class="{ active: isCurrentTab(item.path) }"
|
||||||
|
@click="switchTabByRoute(item)"
|
||||||
|
>
|
||||||
|
<span>{{ item.moduleName }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="query-group">
|
<div class="query-group">
|
||||||
@@ -27,60 +34,105 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="screen-content">
|
<main class="screen-content">
|
||||||
<div v-if="activeTab === 'work'" class="screen-page">
|
<div v-if="isHome" class="screen-page">
|
||||||
<WorkIndex :formParams="FormValues" />
|
<HomePage />
|
||||||
</div>
|
|
||||||
<div v-else-if="activeTab === 'werp'" class="screen-page">
|
|
||||||
<ErpIndex :formParams="FormValues" />
|
|
||||||
</div>
|
</div>
|
||||||
|
<router-view v-else v-slot="{ Component }">
|
||||||
|
<div class="screen-page" v-if="Component">
|
||||||
|
<component :is="Component" />
|
||||||
|
</div>
|
||||||
|
</router-view>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted, computed } from 'vue';
|
||||||
import ErpIndex from './Erp/index.vue';
|
import { useRouter, useRoute } from 'vue-router';
|
||||||
import WorkIndex from './Work/index.vue';
|
import { ElMessage } from 'element-plus';
|
||||||
import { getHomeModuleList } from '@/api/bizApi'
|
import { getHomeModuleList } from '@/api/bizApi'
|
||||||
|
import HomePage from './Home/index.vue'
|
||||||
|
|
||||||
const screenTitle = ref('个人数字化分析看板');
|
const router = useRouter();
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
|
const HOME_TITLE = "个人数字化分析看板";
|
||||||
|
const screenTitle = ref(HOME_TITLE);
|
||||||
const currentYear = new Date().getFullYear().toString();
|
const currentYear = new Date().getFullYear().toString();
|
||||||
|
|
||||||
const FormValues = ref({
|
const allTabs = ref([])
|
||||||
reqParam: currentYear
|
const queryDate = ref(currentYear);
|
||||||
|
|
||||||
|
const getTitle = (title) => {
|
||||||
|
screenTitle.value = title;
|
||||||
|
};
|
||||||
|
|
||||||
|
const isHome = computed(() => {
|
||||||
|
return route.path === '/bigScreen' || route.path === '/';
|
||||||
});
|
});
|
||||||
|
|
||||||
const allTabs = ref([])
|
const goHome = () => {
|
||||||
const activeTab = ref('work')
|
screenTitle.value = HOME_TITLE;
|
||||||
const queryDate = ref();
|
router.push('/bigScreen').catch(() => {});
|
||||||
|
};
|
||||||
|
|
||||||
const switchTab = (key) => {
|
const isCurrentTab = (routePath) => {
|
||||||
activeTab.value = key
|
return route.path === routePath;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
const switchTabByRoute = (item) => {
|
||||||
|
getTitle(item.titleName);
|
||||||
|
if (!item.path) {
|
||||||
|
ElMessage.warning('该模块暂无对应路由');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
router.push({
|
||||||
|
path: item.path,
|
||||||
|
query: {
|
||||||
|
year: queryDate.value,
|
||||||
|
...route.query
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
ElMessage.error('页面切换失败,请重试');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleQuery = () => {
|
const handleQuery = () => {
|
||||||
FormValues.value.reqParam = queryDate.value;
|
if (!queryDate.value) {
|
||||||
}
|
ElMessage.warning('请选择查询年份');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
router.push({
|
||||||
|
path: route.path,
|
||||||
|
query: {
|
||||||
|
...route.query,
|
||||||
|
year: queryDate.value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
async function getList() {
|
async function getList() {
|
||||||
try {
|
try {
|
||||||
const res = await getHomeModuleList()
|
const res = await getHomeModuleList();
|
||||||
allTabs.value = res || []
|
allTabs.value = res || [];
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error)
|
console.error('获取模块列表失败:', error);
|
||||||
allTabs.value = []
|
allTabs.value = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const initApp = () =>{
|
const initApp = () => {
|
||||||
queryDate.value = currentYear;
|
getList();
|
||||||
getList();
|
};
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
initApp();
|
initApp();
|
||||||
|
router.afterEach((to) => {
|
||||||
|
if (to.query.year) {
|
||||||
|
queryDate.value = to.query.year;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -325,6 +377,14 @@ onMounted(() => {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.empty-page {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #e0e6ff;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 1600px) {
|
@media (max-width: 1600px) {
|
||||||
.main-title {
|
.main-title {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import com.mini.mybigscreen.Model.Message;
|
|||||||
import com.mini.mybigscreen.Model.Result;
|
import com.mini.mybigscreen.Model.Result;
|
||||||
import com.mini.mybigscreen.Model.TreeMenu;
|
import com.mini.mybigscreen.Model.TreeMenu;
|
||||||
import com.mini.mybigscreen.biz.domain.HomeMenu;
|
import com.mini.mybigscreen.biz.domain.HomeMenu;
|
||||||
import com.mini.mybigscreen.biz.domain.HomeModule;
|
|
||||||
import com.mini.mybigscreen.biz.domain.HomeRoleMenu;
|
import com.mini.mybigscreen.biz.domain.HomeRoleMenu;
|
||||||
import com.mini.mybigscreen.biz.mapper.HomeMenuMapper;
|
import com.mini.mybigscreen.biz.mapper.HomeMenuMapper;
|
||||||
import com.mini.mybigscreen.biz.service.HomeMenuService;
|
import com.mini.mybigscreen.biz.service.HomeMenuService;
|
||||||
|
|||||||
@@ -2,12 +2,16 @@ package com.mini.mybigscreen.biz.controller;
|
|||||||
|
|
||||||
import com.mini.mybigscreen.Model.Message;
|
import com.mini.mybigscreen.Model.Message;
|
||||||
import com.mini.mybigscreen.Model.Result;
|
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.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* 前端控制器
|
* 前端控制器
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author gaoxq
|
* @author gaoxq
|
||||||
@@ -17,6 +21,13 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
@RequestMapping("/biz/homeModule")
|
@RequestMapping("/biz/homeModule")
|
||||||
public class HomeModuleController {
|
public class HomeModuleController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private HomeModuleService moduleService;
|
||||||
|
|
||||||
|
@GetMapping("list")
|
||||||
|
public Result<?> getList() {
|
||||||
|
return Result.success(moduleService.list());
|
||||||
|
}
|
||||||
|
|
||||||
public Result<Message> save() {
|
public Result<Message> save() {
|
||||||
return Result.success(new Message("数据新增成功", 200));
|
return Result.success(new Message("数据新增成功", 200));
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -4,12 +4,8 @@ import com.baomidou.mybatisplus.annotation.IdType;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableField;
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
|
||||||
import java.io.Serial;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
import com.mini.mybigscreen.Model.BaseEntity;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
@@ -19,14 +15,13 @@ import lombok.Setter;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author gaoxq
|
* @author gaoxq
|
||||||
* @since 2026-02-27
|
* @since 2026-03-07
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@Setter
|
@Setter
|
||||||
@TableName("biz_home_module")
|
@TableName("biz_home_module")
|
||||||
public class HomeModule extends BaseEntity implements Serializable {
|
public class HomeModule implements Serializable {
|
||||||
|
|
||||||
@Serial
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
@TableField("create_time")
|
@TableField("create_time")
|
||||||
@@ -47,9 +42,18 @@ public class HomeModule extends BaseEntity implements Serializable {
|
|||||||
@TableField("module_code")
|
@TableField("module_code")
|
||||||
private String moduleCode;
|
private String moduleCode;
|
||||||
|
|
||||||
|
@TableField("path")
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
@TableField("title_name")
|
||||||
|
private String titleName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 说明描述
|
* 说明描述
|
||||||
*/
|
*/
|
||||||
@TableField("remark")
|
@TableField("remark")
|
||||||
private String remark;
|
private String remark;
|
||||||
|
|
||||||
|
@TableField("ustatus")
|
||||||
|
private String ustatus;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
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> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ import com.mini.mybigscreen.biz.domain.HomeModule;
|
|||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author gaoxq
|
* @author gaoxq
|
||||||
* @since 2026-02-27
|
* @since 2026-03-07
|
||||||
*/
|
*/
|
||||||
public interface HomeModuleMapper extends MPJBaseMapper<HomeModule> {
|
public interface HomeModuleMapper extends MPJBaseMapper<HomeModule> {
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
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> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
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 {
|
||||||
|
|
||||||
|
}
|
||||||
18
src/main/resources/mapper/HomeModuleGroupMapper.xml
Normal file
18
src/main/resources/mapper/HomeModuleGroupMapper.xml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.mini.mybigscreen.biz.mapper.HomeModuleGroupMapper">
|
||||||
|
|
||||||
|
<!-- 通用查询映射结果 -->
|
||||||
|
<resultMap id="BaseResultMap" type="com.mini.mybigscreen.biz.domain.HomeModuleGroup">
|
||||||
|
<id column="group_id" property="groupId" />
|
||||||
|
<result column="create_time" property="createTime" />
|
||||||
|
<result column="group_name" property="groupName" />
|
||||||
|
<result column="ustatus" property="ustatus" />
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<!-- 通用查询结果列 -->
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
create_time, group_id, group_name, ustatus
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
@@ -8,12 +8,15 @@
|
|||||||
<result column="create_time" property="createTime" />
|
<result column="create_time" property="createTime" />
|
||||||
<result column="module_name" property="moduleName" />
|
<result column="module_name" property="moduleName" />
|
||||||
<result column="module_code" property="moduleCode" />
|
<result column="module_code" property="moduleCode" />
|
||||||
|
<result column="path" property="path" />
|
||||||
|
<result column="title_name" property="titleName" />
|
||||||
<result column="remark" property="remark" />
|
<result column="remark" property="remark" />
|
||||||
|
<result column="ustatus" property="ustatus" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<!-- 通用查询结果列 -->
|
<!-- 通用查询结果列 -->
|
||||||
<sql id="Base_Column_List">
|
<sql id="Base_Column_List">
|
||||||
create_time, module_id, module_name, module_code, remark
|
create_time, module_id, module_name, module_code, path, title_name, remark, ustatus
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|||||||
Reference in New Issue
Block a user