From 18c0ffb02bbc0aa7eeea1d79a210260880b964f8 Mon Sep 17 00:00:00 2001
From: lbq <1065079612@qq.com>
Date: 星期三, 07 一月 2026 11:07:21 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/devlop-phyz' into devlop-phyz
---
rsf-admin/src/page/menuPda/index.jsx | 15
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java | 2
rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/MenuPdaMapper.java | 12
rsf-admin/src/page/pdaRoleMenu/index.jsx | 18
rsf-server/src/main/java/com/vincent/rsf/server/system/service/impl/PdaRoleMenuServiceImpl.java | 24
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/InBoundController.java | 34
rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java | 8
rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuEdit.jsx | 97 ++
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/MenuPdaService.java | 8
rsf-admin/src/page/menuPda/MenuPdaList.jsx | 456 ++++++++++
rsf-server/src/main/java/com/vincent/rsf/server/common/config/MybatisPlusConfig.java | 2
rsf-server/src/main/java/com/vincent/rsf/server/api/entity/params/PdaGeneralParam.java | 15
rsf-admin/src/i18n/zh.js | 21
rsf-admin/src/page/menuPda/MenuPdaEdit.jsx | 225 +++++
rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MenuPdaController.java | 157 +++
rsf-server/src/main/java/com/vincent/rsf/server/system/mapper/PdaRoleMenuMapper.java | 22
rsf-admin/src/i18n/en.js | 21
rsf-admin/src/page/ResourceContent.js | 9
rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/InBoundServiceImpl.java | 14
rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuPanel.jsx | 63 +
rsf-server/src/main/resources/application-dev.yml | 2
rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuCreate.jsx | 125 ++
rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/MenuPdaServiceImpl.java | 12
rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/MenuPda.java | 258 ++++++
rsf-server/src/main/java/com/vincent/rsf/server/api/service/InBoundService.java | 10
rsf-open-api/src/main/resources/application-dev.yml | 4
rsf-server/src/main/resources/mapper/manager/MenuPdaMapper.xml | 5
rsf-admin/src/i18n/core/chineseMessages.js | 1
rsf-server/src/main/java/com/vincent/rsf/server/system/service/PdaRoleMenuService.java | 14
rsf-server/src/main/resources/mapper/system/PdaRoleMenuMapper.xml | 37
rsf-server/src/main/java/pdaRoleMenu.sql | 23
rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuList.jsx | 154 +++
rsf-admin/src/page/system/role/RoleList.jsx | 69 +
rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/CheckOrderSchedules.java | 8
rsf-server/src/main/java/com/vincent/rsf/server/system/controller/PdaRoleMenuController.java | 58 +
rsf-admin/src/page/system/role/AssignPermissions_pda.jsx | 380 +++++++++
rsf-server/src/main/java/com/vincent/rsf/server/system/entity/PdaRoleMenu.java | 50 +
rsf-server/src/main/java/menuPda.sql | 35
38 files changed, 2,448 insertions(+), 20 deletions(-)
diff --git a/rsf-admin/src/i18n/core/chineseMessages.js b/rsf-admin/src/i18n/core/chineseMessages.js
index 59a0d7d..1565801 100644
--- a/rsf-admin/src/i18n/core/chineseMessages.js
+++ b/rsf-admin/src/i18n/core/chineseMessages.js
@@ -25,6 +25,7 @@
save: "淇濆瓨",
search: "鎼滅储",
select_all_button: "鍏ㄩ儴閫変腑",
+ select_all: "鍏ㄩ儴閫変腑",
select_row: "閫変腑涓�琛�",
show: "鏄剧ず",
sort: "鎺掑簭",
diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js
index 2f09aff..d466567 100644
--- a/rsf-admin/src/i18n/en.js
+++ b/rsf-admin/src/i18n/en.js
@@ -219,6 +219,7 @@
stockStatistic: 'Stock Statistic',
statisticCount: 'Statistic Count',
preparation: "澶囨枡鍗�",
+ menuPda: 'MenuPda',
},
table: {
field: {
@@ -311,6 +312,26 @@
button: 'Button',
}
},
+ menuPda: {
+ name: "name",
+ parentId: "parent id",
+ parentName: "higher",
+ path: "path",
+ pathName: "pathName",
+ route: "route",
+ component: "component",
+ brief: "brief",
+ code: "code",
+ type: "type",
+ authority: "authority",
+ icon: "icon",
+ sort: "sort",
+ meta: "meta",
+ enums: {
+ menu: 'Menu',
+ button: 'Button',
+ }
+ },
user: {
username: "username",
password: "password",
diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js
index 6563ae3..0256cf5 100644
--- a/rsf-admin/src/i18n/zh.js
+++ b/rsf-admin/src/i18n/zh.js
@@ -235,6 +235,7 @@
platform: '骞冲彴绠$悊',
freeze: '搴撳瓨鍐荤粨',
transferPoces: '璋冩嫧绠$悊',
+ menuPda: 'PDA鑿滃崟',
},
table: {
field: {
@@ -340,6 +341,26 @@
button: '鎸夐挳',
}
},
+ menuPda: {
+ name: "鑿滃崟鍚嶇О",
+ parentId: "涓婄骇鑿滃崟ID",
+ parentName: "涓婄骇鑿滃崟",
+ path: "璺緞",
+ pathName: "璺緞鍚�",
+ route: "璺敱鍦板潃",
+ component: "缁勪欢",
+ brief: "绠�杩�",
+ code: "鏍囪瘑",
+ type: "绫诲瀷",
+ authority: "閴存潈",
+ icon: "鍥炬爣",
+ sort: "鎺掑簭",
+ meta: "鍏�",
+ enums: {
+ menu: '鑿滃崟',
+ button: '鎸夐挳',
+ }
+ },
user: {
username: "璐﹀彿",
password: "瀵嗙爜",
diff --git a/rsf-admin/src/page/ResourceContent.js b/rsf-admin/src/page/ResourceContent.js
index 07d6451..505e0bf 100644
--- a/rsf-admin/src/page/ResourceContent.js
+++ b/rsf-admin/src/page/ResourceContent.js
@@ -64,6 +64,7 @@
import inStatisticItem from './statistics/inStockItem';
import statisticCount from './statistics/stockStatisticNum';
import preparation from "./orders/preparation";
+import menuPda from './menuPda';
// import locItem from "./basicInfo/locItem";
const ResourceContent = (node) => {
@@ -174,13 +175,13 @@
return transfer;
case "locRevise":
return locRevise;
- case "locDeadReport":
+ case "locDeadReport":
return locDeadReport;
case "inStatistic":
return inStatistic;
- case "outStatistic":
+ case "outStatistic":
return outStatistic;
- case "outStatisticItem":
+ case "outStatisticItem":
return outStatisticItem;
case "inStatisticItem":
return inStatisticItem;
@@ -188,6 +189,8 @@
return statisticCount;
case "preparation":
return preparation;
+ case 'menuPda':
+ return menuPda;
// case "locItem":
// return locItem;
default:
diff --git a/rsf-admin/src/page/menuPda/MenuPdaEdit.jsx b/rsf-admin/src/page/menuPda/MenuPdaEdit.jsx
new file mode 100644
index 0000000..3560161
--- /dev/null
+++ b/rsf-admin/src/page/menuPda/MenuPdaEdit.jsx
@@ -0,0 +1,225 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+ CreateBase,
+ useTranslate,
+ TextInput,
+ NumberInput,
+ BooleanInput,
+ DateInput,
+ SaveButton,
+ SelectInput,
+ ReferenceInput,
+ ReferenceArrayInput,
+ AutocompleteInput,
+ Toolbar,
+ required,
+ useNotify,
+ Form,
+ useUpdate,
+ useCreate,
+ useCreateContext,
+} from 'react-admin';
+import {
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Stack,
+ Grid,
+ Box,
+} from '@mui/material';
+import DialogCloseButton from "@/page/components/DialogCloseButton";
+import StatusSelectInput from "@/page/components/StatusSelectInput";
+import MemoInput from "@/page/components/MemoInput";
+import TreeSelectInput from "@/page/components/TreeSelectInput";
+
+const EditContent = ({ editRecord }) => {
+ const { resource } = useCreateContext();
+ return (
+ <Grid container rowSpacing={2} columnSpacing={2}>
+ <Grid item xs={6} display="flex" gap={1}>
+ <TreeSelectInput
+ label="table.field.menu.parentName"
+ value={editRecord?.parentId}
+ isTranslate
+ resource={resource}
+ />
+ </Grid>
+ <Grid item xs={6} display="flex" gap={1}>
+ <TextInput
+ label="table.field.menu.name"
+ source="name"
+ parse={v => v}
+ validate={required()}
+ />
+ </Grid>
+ <Grid item xs={6} display="flex" gap={1}>
+ <TextInput
+ label="table.field.menu.route"
+ source="route"
+ validate={required()}
+ parse={v => v}
+ />
+ </Grid>
+ <Grid item xs={6} display="flex" gap={1}>
+ <TextInput
+ label="table.field.menu.component"
+ source="component"
+ parse={v => v}
+ />
+ </Grid>
+ <Grid item xs={6} display="flex" gap={1}>
+ <SelectInput
+ label="table.field.menu.type"
+ source="type"
+ validate={required()}
+ choices={[
+ { id: 0, name: 'table.field.menu.enums.menu' },
+ { id: 1, name: 'table.field.menu.enums.button' },
+ ]}
+ />
+ </Grid>
+ <Grid item xs={6} display="flex" gap={1}>
+ <TextInput
+ label="table.field.menu.authority"
+ source="authority"
+ parse={v => v}
+ />
+ </Grid>
+ <Grid item xs={6} display="flex" gap={1}>
+ <TextInput
+ label="table.field.menu.icon"
+ source="icon"
+ parse={v => v}
+ />
+ </Grid>
+ <Grid item xs={6} display="flex" gap={1}>
+ <NumberInput
+ label="table.field.menu.sort"
+ source="sort"
+ />
+ </Grid>
+
+ <Grid item xs={6} display="flex" gap={1}>
+ <StatusSelectInput />
+ </Grid>
+ <Grid item xs={6} display="flex" gap={1}>
+ <TextInput
+ label="common.field.memo"
+ source="memo"
+ parse={v => v}
+ fullWidth
+ multiline
+ minRows={2}
+ autoFocus
+ />
+ </Grid>
+ </Grid>
+ )
+}
+
+const MenuPdaEdit = (props) => {
+ const { editRecord, open, setOpen, callback, resource } = props;
+
+ const translate = useTranslate();
+ const notify = useNotify();
+
+ const [update] = useUpdate();
+ const [create] = useCreate();
+
+ const handleClose = (event, reason) => {
+ if (reason !== "backdropClick") {
+ setOpen(false);
+ }
+ };
+
+ const handleSuccess = async (data) => {
+ setOpen(false);
+ callback();
+ notify('common.response.success', { type: 'info' });
+ };
+
+ const handleError = async (data) => {
+ notify('common.response.fail', { type: 'error' });
+ };
+
+ const onSubmit = (data) => {
+ const _params = { ...data };
+ if (editRecord) {
+ if (_params.parentId === editRecord.id) {
+ notify('common.response.dataError', { type: 'error' });
+ return;
+ }
+ update(
+ resource,
+ {
+ id: editRecord.id,
+ data: _params,
+ },
+ {
+ onSuccess: () => {
+ handleSuccess();
+ },
+ onError: (error) => {
+ handleError();
+ },
+ }
+ );
+ } else {
+ create(
+ resource,
+ { data: _params },
+ {
+ onSuccess: () => {
+ handleSuccess();
+ },
+ onError: (error) => {
+ handleError();
+ },
+ }
+ );
+ }
+ };
+
+ return (
+ <>
+ <CreateBase>
+ <Dialog
+ open={open}
+ onClose={handleClose}
+ aria-labelledby="form-dialog-title"
+ fullWidth
+ disableRestoreFocus
+ maxWidth="md" // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
+ >
+ <Form record={editRecord} onSubmit={onSubmit}>
+ <DialogTitle id="form-dialog-title" sx={{
+ position: 'sticky',
+ top: 0,
+ backgroundColor: 'background.paper',
+ zIndex: 1000
+ }}
+ >
+ {editRecord ? translate('update.title') : translate('create.title')}
+ <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
+ <DialogCloseButton onClose={handleClose} />
+ </Box>
+ </DialogTitle>
+ <DialogContent sx={{ mt: 2 }}>
+ <EditContent
+ editRecord={editRecord}
+ />
+ </DialogContent>
+ <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+ <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }} >
+ <SaveButton />
+ </Toolbar>
+ </DialogActions>
+ </Form>
+ </Dialog>
+ </CreateBase>
+ </>
+ )
+}
+
+export default MenuPdaEdit;
diff --git a/rsf-admin/src/page/menuPda/MenuPdaList.jsx b/rsf-admin/src/page/menuPda/MenuPdaList.jsx
new file mode 100644
index 0000000..6bde7a7
--- /dev/null
+++ b/rsf-admin/src/page/menuPda/MenuPdaList.jsx
@@ -0,0 +1,456 @@
+import React from 'react';
+import {
+ Title,
+ useTranslate,
+ useNotify,
+ useRedirect,
+ useRefresh,
+ useDelete,
+} from 'react-admin';
+import { styled } from '@mui/material/styles';
+import {
+ Box,
+ Collapse,
+ IconButton,
+ Table,
+ TableBody,
+ TableCell,
+ TableContainer,
+ TableHead,
+ TableRow,
+ Paper,
+ Card,
+ Typography,
+ TextField,
+ Tooltip,
+ Button,
+ Chip,
+ LinearProgress,
+} from '@mui/material';
+import { Add, Edit, Delete } from '@mui/icons-material';
+import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
+import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
+import RefreshIcon from '@mui/icons-material/Refresh';
+import request from '@/utils/request';
+import DeptEdit from './MenuPdaEdit';
+import * as Icons from '@mui/icons-material';
+
+const RESOURCE = 'menuPda';
+const TITLE = 'menu.menuPda';
+
+const columns = [
+ {
+ id: 'name',
+ label: 'table.field.menuPda.name',
+ minWidth: 200,
+ },
+ {
+ id: 'icon',
+ label: 'table.field.menuPda.icon',
+ minWidth: 80,
+ format: (iconStr) => {
+ if (iconStr) {
+ const IconComponent = getIconComponent(iconStr);
+ if (IconComponent) {
+ return <IconComponent />;
+ }
+ }
+ }
+ },
+ {
+ id: 'route',
+ label: 'table.field.menuPda.route',
+ minWidth: 80,
+ },
+ {
+ id: 'component',
+ label: 'table.field.menuPda.component',
+ minWidth: 100,
+ },
+ {
+ id: 'authority',
+ label: 'table.field.menuPda.authority',
+ minWidth: 100,
+ },
+ {
+ id: 'type',
+ label: 'table.field.menuPda.type',
+ minWidth: 100,
+ format: (val) => {
+ if (Number(val) === 0) {
+ return <Chip variant='outlined' label="Menu" color="primary" size='small' />;
+ } else {
+ return <Chip variant='outlined' label="Button" color="default" size='small' />;
+ }
+ }
+ },
+ {
+ id: 'sort',
+ label: 'table.field.menuPda.sort',
+ minWidth: 80,
+ format: (val) => {
+ return <Typography variant='body2' sx={{ fontWeight: 'bold' }}>{val}</Typography>
+ }
+ },
+ // {
+ // id: 'updateTime',
+ // label: 'common.field.updateTime',
+ // minWidth: 120,
+ // format: (val) => {
+ // return new Date(val).toLocaleString();
+ // }
+ // },
+ {
+ id: 'id',
+ label: 'common.field.id',
+ minWidth: 80,
+ },
+ {
+ id: 'actions',
+ label: 'common.field.opt',
+ minWidth: 100,
+ },
+];
+
+const getIconComponent = (iconStr) => {
+ return Icons[iconStr] || null;
+};
+
+const StyledTableRow = styled(TableRow)(({ theme }) => ({
+ '& .MuiButtonBase-root': {
+ padding: '0px 8px'
+ }
+}));
+
+const StyledTableCell = styled(TableCell)(({ theme }) => ({
+ overflow: 'hidden',
+ textOverflow: 'ellipsis',
+ whiteSpace: 'nowrap',
+ maxWidth: 600,
+ // 纭繚鎵�鏈夊崟鍏冩牸鏈夊熀鏈殑鍐呰竟璺�
+ padding: '8px 16px',
+}));
+
+const TreeTableRow = (props) => {
+ const { row, depth = 0, openNodes, setOpenNodes, onEdit, onDelete } = props;
+ const translate = useTranslate();
+
+ const toggleNode = (id) => {
+ setOpenNodes(prevState => ({ ...prevState, [id]: !prevState[id] }));
+ };
+
+ const isOpen = openNodes[row.id] || false;
+
+ // 鏇存槑鏄剧殑閫忔槑搴︽笎鍙�
+ const getOpacity = (currentDepth) => {
+ // 绗竴绾э細100%锛岀浜岀骇锛�75%锛岀涓夌骇锛�50%锛岀鍥涚骇锛�40%
+ const opacities = [1, 0.9, 0.8, 0.7];
+ return opacities[currentDepth] || 0.4;
+ };
+
+ const opacity = getOpacity(depth);
+
+ return (
+ <React.Fragment>
+ <StyledTableRow
+ hover
+ tabIndex={-1}
+ key={row.id}
+ sx={{
+ opacity: depth > 0 ? opacity : 1,
+ // 娣诲姞鑳屾櫙鑹叉笎鍙樺寮烘晥鏋�
+ backgroundColor: depth > 0 ? `rgba(0, 0, 0, ${0.02 * (3 - depth)})` : 'inherit',
+ }}
+ >
+ <StyledTableCell sx={{
+ padding: 0,
+ width: 60,
+ // 杩涗竴姝ュ噺灏忕缉杩涜窛绂诲埌12px
+ paddingLeft: depth * 4
+ }}>
+ {row.children && row.children.length > 0 && (
+ <IconButton
+ aria-label="expand row"
+ size="small"
+ onClick={() => toggleNode(row.id)}
+ sx={{
+ opacity: depth > 0 ? opacity : 1,
+ }}
+ >
+ {isOpen ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
+ </IconButton>
+ )}
+ </StyledTableCell>
+ {columns.map((column, idx) => {
+ if (column.id !== 'actions') {
+ let value = row[column.id];
+ if (column.id === 'name' && row['type'] === 0) {
+ value = translate(value);
+ }
+ return (
+ <StyledTableCell
+ key={column.id}
+ align={column.align || 'left'}
+ style={{
+ // 鍚嶇О鍒椾篃浣跨敤12px缂╄繘
+ paddingLeft: idx === 0 ? (depth * 24 + 16) : 16,
+ // opacity: column.id === 'icon' && .6
+ }}
+ onClick={() => column.id === 'name' && toggleNode(row.id)}
+ sx={{
+ opacity: column.id === 'icon' ? 0.6 : (depth > 0 ? opacity : 1),
+ fontWeight: 400,
+ // 浣跨敤瀛椾綋澶у皬鎴栭鑹叉潵鍖哄垎灞傜骇
+ fontSize: depth === 0 ? '0.95rem' : '0.9rem',
+ // 鎴栬�呬娇鐢ㄤ笉鍚岀殑棰滆壊
+ color: depth === 0 ? 'text.primary' : `rgba(0, 0, 0, ${opacity})`,
+ }}
+ >
+ {column.format ? column.format(value) : value}
+ </StyledTableCell>
+ )
+ }
+ })}
+ <StyledTableCell>
+ <Tooltip title="Edit">
+ <IconButton
+ onClick={() => onEdit(row)}
+ sx={{
+ opacity: depth > 0 ? opacity : 1,
+ }}
+ size="small"
+ >
+ <Edit />
+ </IconButton>
+ </Tooltip>
+ <Tooltip title="Delete">
+ <IconButton
+ onClick={() => onDelete(row)}
+ sx={{
+ opacity: depth > 0 ? opacity : 1,
+ }}
+ size="small"
+ >
+ <Delete />
+ </IconButton>
+ </Tooltip>
+ </StyledTableCell>
+ </StyledTableRow>
+ {row.children && row.children.length > 0 && isOpen && (
+ row.children.map((child) => (
+ <TreeTableRow
+ key={child.id}
+ row={child}
+ depth={depth + 1}
+ onEdit={onEdit}
+ onDelete={onDelete}
+ openNodes={openNodes}
+ setOpenNodes={setOpenNodes}
+ />
+ ))
+ )}
+ </React.Fragment>
+ );
+};
+
+const MenuPdaList = () => {
+ const translate = useTranslate();
+ const notify = useNotify();
+ const redirect = useRedirect();
+ const refresh = useRefresh();
+ const [deleteOne] = useDelete();
+
+ const [treeData, setTreeData] = React.useState(null);
+ const [filter, setFilter] = React.useState("");
+ const [createDialog, setCreateDialog] = React.useState(false);
+ const [editRecord, setEditRecord] = React.useState(null);
+ const [openNodes, setOpenNodes] = React.useState({});
+ const [expandAll, setExpandAll] = React.useState(false);
+ const notifyState = React.useRef({ last: '', at: 0 });
+ const pushNotify = React.useCallback((type, msg) => {
+ const text = typeof msg === 'string' ? msg : (msg || '');
+ const now = Date.now();
+ if (notifyState.current.last === text && now - notifyState.current.at < 1500) return;
+ notifyState.current = { last: text, at: now };
+ notify(text, { type, messageArgs: { _: text } });
+ }, [notify]);
+
+ const http = async () => {
+ const res = await request.post(RESOURCE + '/tree', {
+ condition: filter
+ });
+ if (res?.data?.code === 200) {
+ setTreeData(res.data.data);
+ } else {
+ const msg = translate('ra.notification.http_error', { _: res?.data?.msg || 'Request failed' });
+ pushNotify('warning', msg);
+ }
+ }
+
+ React.useEffect(() => {
+ http();
+ }, [filter]);
+
+ const handleRefresh = () => {
+ http();
+ };
+
+ const handleAdd = () => {
+ setEditRecord(null);
+ setCreateDialog(true);
+ };
+
+ const handleEdit = (node) => {
+ setEditRecord(node);
+ setCreateDialog(true);
+ };
+
+ const handleDelete = (node) => {
+ if (window.confirm(translate('ra.message.delete_content'))) {
+ deleteOne(
+ RESOURCE,
+ { id: node.id },
+ {
+ onSuccess: () => {
+ handleRefresh();
+ const msg = translate('ra.message.delete_success', { _: 'Deleted successfully' });
+ pushNotify('success', msg);
+ },
+ onError: (error) => {
+ const msg = translate('ra.notification.http_error', { _: error?.message || 'Network error' });
+ pushNotify('error', msg);
+ },
+ }
+ );
+ }
+ };
+
+ const toggleExpandAll = () => {
+ setExpandAll(prevExpandAll => {
+ const newExpandAll = !prevExpandAll;
+ const newOpenNodes = {};
+ const updateOpenNodes = (nodes) => {
+ if (!nodes) return;
+ nodes.forEach(node => {
+ newOpenNodes[node.id] = newExpandAll;
+ if (node.children) {
+ updateOpenNodes(node.children);
+ }
+ });
+ };
+ updateOpenNodes(treeData);
+ setOpenNodes(newOpenNodes);
+ return newExpandAll;
+ });
+ };
+
+ return (
+ <div>
+ <DeptEdit
+ editRecord={editRecord}
+ open={createDialog}
+ setOpen={setCreateDialog}
+ callback={() => {
+ handleRefresh();
+ }}
+ resource={RESOURCE}
+ />
+ <Title title={TITLE} />
+ <Box sx={{ mt: 2, mr: 3, mb: 1, display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
+ <Box width={300} >
+ <Button
+ variant="outlined"
+ color="primary"
+ startIcon={expandAll ? <KeyboardArrowDownIcon /> : <KeyboardArrowRightIcon />}
+ onClick={toggleExpandAll}
+ sx={{ ml: 1 }}
+ >
+ {expandAll ? translate('common.action.collapseAll') : translate('common.action.expandAll')}
+ </Button>
+ {/* <TextField
+ label="Search"
+ value={filter}
+ onChange={({ target }) => {
+ setFilter(target.value)
+ }}
+ variant="filled"
+ size="small"
+ margin="dense"
+ fullWidth
+ /> */}
+ </Box>
+ <Box>
+ <Button
+ variant="outlined"
+ color="primary"
+ startIcon={<RefreshIcon />}
+ onClick={handleRefresh}
+ sx={{ ml: 1 }}
+ >
+ {translate('ra.action.refresh')}
+ </Button>
+ <Button
+ variant="outlined"
+ color="primary"
+ startIcon={<Add />}
+ onClick={handleAdd}
+ sx={{ ml: 1 }}
+ >
+ {translate('ra.action.add')}
+ </Button>
+ </Box>
+ </Box>
+ <Card sx={{
+ position: 'relative',
+ }}>
+ {!treeData && (
+ <LinearProgress
+ sx={{
+ height: "3px",
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ right: 0,
+ }}
+ />
+ )}
+ <TableContainer component={Paper}>
+ <Table size="small">
+ <TableHead>
+ <TableRow>
+ <StyledTableCell sx={{ padding: 0, width: 60 }} />
+ {columns.map((column, idx) => (
+ <StyledTableCell
+ key={idx}
+ align={column.align || 'left'}
+ style={{
+ minWidth: column.minWidth
+ }}
+ >
+ {translate(column.label)}
+ </StyledTableCell>
+ ))}
+ </TableRow>
+ </TableHead>
+ <TableBody>
+ {treeData && treeData.length > 0 && (
+ treeData.map((row) => (
+ <TreeTableRow
+ key={row.id}
+ row={row}
+ onEdit={handleEdit}
+ onDelete={handleDelete}
+ openNodes={openNodes}
+ setOpenNodes={setOpenNodes}
+ />
+ ))
+ )}
+ </TableBody>
+ </Table>
+ </TableContainer>
+ </Card>
+ </div>
+ );
+};
+
+export default MenuPdaList;
diff --git a/rsf-admin/src/page/menuPda/index.jsx b/rsf-admin/src/page/menuPda/index.jsx
new file mode 100644
index 0000000..7e791c4
--- /dev/null
+++ b/rsf-admin/src/page/menuPda/index.jsx
@@ -0,0 +1,15 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+ ListGuesser,
+ EditGuesser,
+ ShowGuesser,
+} from "react-admin";
+
+import MenuPdaList from "./MenuPdaList";
+
+export default {
+ list: MenuPdaList,
+ recordRepresentation: (record) => {
+ return `${record.name}`
+ }
+};
\ No newline at end of file
diff --git a/rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuCreate.jsx b/rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuCreate.jsx
new file mode 100644
index 0000000..1b9e664
--- /dev/null
+++ b/rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuCreate.jsx
@@ -0,0 +1,125 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+ CreateBase,
+ useTranslate,
+ TextInput,
+ NumberInput,
+ BooleanInput,
+ DateInput,
+ SaveButton,
+ SelectInput,
+ ReferenceInput,
+ ReferenceArrayInput,
+ AutocompleteInput,
+ Toolbar,
+ required,
+ useDataProvider,
+ useNotify,
+ Form,
+ useCreateController,
+} from 'react-admin';
+import {
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Stack,
+ Grid,
+ Box,
+} from '@mui/material';
+import DialogCloseButton from "../components/DialogCloseButton";
+import StatusSelectInput from "../components/StatusSelectInput";
+import MemoInput from "../components/MemoInput";
+
+const PdaRoleMenuCreate = (props) => {
+ const { open, setOpen } = props;
+
+ const translate = useTranslate();
+ const notify = useNotify();
+
+ const handleClose = (event, reason) => {
+ if (reason !== "backdropClick") {
+ setOpen(false);
+ }
+ };
+
+ const handleSuccess = async (data) => {
+ setOpen(false);
+ notify('common.response.success');
+ };
+
+ const handleError = async (error) => {
+ notify(error.message || 'common.response.fail', { type: 'error', messageArgs: { _: error.message } });
+ };
+
+ return (
+ <>
+ <CreateBase
+ record={{}}
+ transform={(data) => {
+ return data;
+ }}
+ mutationOptions={{ onSuccess: handleSuccess, onError: handleError }}
+ >
+ <Dialog
+ open={open}
+ onClose={handleClose}
+ aria-labelledby="form-dialog-title"
+ fullWidth
+ disableRestoreFocus
+ maxWidth="md" // 'xs' | 'sm' | 'md' | 'lg' | 'xl'
+ >
+ <Form>
+ <DialogTitle id="form-dialog-title" sx={{
+ position: 'sticky',
+ top: 0,
+ backgroundColor: 'background.paper',
+ zIndex: 1000
+ }}
+ >
+ {translate('create.title')}
+ <Box sx={{ position: 'absolute', top: 8, right: 8, zIndex: 1001 }}>
+ <DialogCloseButton onClose={handleClose} />
+ </Box>
+ </DialogTitle>
+ <DialogContent sx={{ mt: 2 }}>
+ <Grid container rowSpacing={2} columnSpacing={2}>
+ <Grid item xs={6} display="flex" gap={1}>
+ <NumberInput
+ label="table.field.pdaRoleMenu.roleId"
+ source="roleId"
+ autoFocus
+ validate={required()}
+ />
+ </Grid>
+ <Grid item xs={6} display="flex" gap={1}>
+ <NumberInput
+ label="table.field.pdaRoleMenu.menuId"
+ source="menuId"
+ validate={required()}
+ />
+ </Grid>
+
+ <Grid item xs={6} display="flex" gap={1}>
+ <StatusSelectInput />
+ </Grid>
+ <Grid item xs={12} display="flex" gap={1}>
+ <Stack direction="column" spacing={1} width={'100%'}>
+ <MemoInput />
+ </Stack>
+ </Grid>
+ </Grid>
+ </DialogContent>
+ <DialogActions sx={{ position: 'sticky', bottom: 0, backgroundColor: 'background.paper', zIndex: 1000 }}>
+ <Toolbar sx={{ width: '100%', justifyContent: 'space-between' }} >
+ <SaveButton />
+ </Toolbar>
+ </DialogActions>
+ </Form>
+ </Dialog>
+ </CreateBase>
+ </>
+ )
+}
+
+export default PdaRoleMenuCreate;
diff --git a/rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuEdit.jsx b/rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuEdit.jsx
new file mode 100644
index 0000000..7e7d4d8
--- /dev/null
+++ b/rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuEdit.jsx
@@ -0,0 +1,97 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+ Edit,
+ SimpleForm,
+ FormDataConsumer,
+ useTranslate,
+ TextInput,
+ NumberInput,
+ BooleanInput,
+ DateInput,
+ SelectInput,
+ ReferenceInput,
+ ReferenceArrayInput,
+ AutocompleteInput,
+ SaveButton,
+ Toolbar,
+ Labeled,
+ NumberField,
+ required,
+ useRecordContext,
+ DeleteButton,
+} from 'react-admin';
+import { useWatch, useFormContext } from "react-hook-form";
+import { Stack, Grid, Box, Typography } from '@mui/material';
+import * as Common from '@/utils/common';
+import { EDIT_MODE, REFERENCE_INPUT_PAGESIZE } from '@/config/setting';
+import EditBaseAside from "../components/EditBaseAside";
+import CustomerTopToolBar from "../components/EditTopToolBar";
+import MemoInput from "../components/MemoInput";
+import StatusSelectInput from "../components/StatusSelectInput";
+
+const FormToolbar = () => {
+ const { getValues } = useFormContext();
+
+ return (
+ <Toolbar sx={{ justifyContent: 'space-between' }}>
+ <SaveButton />
+ <DeleteButton mutationMode="optimistic" />
+ </Toolbar>
+ )
+}
+
+const PdaRoleMenuEdit = () => {
+ const translate = useTranslate();
+
+ return (
+ <Edit
+ redirect="list"
+ mutationMode={EDIT_MODE}
+ actions={<CustomerTopToolBar />}
+ aside={<EditBaseAside />}
+ >
+ <SimpleForm
+ shouldUnregister
+ warnWhenUnsavedChanges
+ toolbar={<FormToolbar />}
+ mode="onTouched"
+ defaultValues={{}}
+ // validate={(values) => { }}
+ >
+ <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}>
+ <Grid item xs={12} md={8}>
+ <Typography variant="h6" gutterBottom>
+ {translate('common.edit.title.main')}
+ </Typography>
+ <Stack direction='row' gap={2}>
+ <NumberInput
+ label="table.field.pdaRoleMenu.roleId"
+ source="roleId"
+ autoFocus
+ validate={required()}
+ />
+ </Stack>
+ <Stack direction='row' gap={2}>
+ <NumberInput
+ label="table.field.pdaRoleMenu.menuId"
+ source="menuId"
+ validate={required()}
+ />
+ </Stack>
+
+ </Grid>
+ <Grid item xs={12} md={4}>
+ <Typography variant="h6" gutterBottom>
+ {translate('common.edit.title.common')}
+ </Typography>
+ <StatusSelectInput />
+ <Box mt="2em" />
+ <MemoInput />
+ </Grid>
+ </Grid>
+ </SimpleForm>
+ </Edit >
+ )
+}
+
+export default PdaRoleMenuEdit;
diff --git a/rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuList.jsx b/rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuList.jsx
new file mode 100644
index 0000000..4271ecd
--- /dev/null
+++ b/rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuList.jsx
@@ -0,0 +1,154 @@
+import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
+import { useNavigate } from 'react-router-dom';
+import {
+ List,
+ DatagridConfigurable,
+ SearchInput,
+ TopToolbar,
+ SelectColumnsButton,
+ EditButton,
+ FilterButton,
+ CreateButton,
+ ExportButton,
+ BulkDeleteButton,
+ WrapperField,
+ useRecordContext,
+ useTranslate,
+ useNotify,
+ useListContext,
+ FunctionField,
+ TextField,
+ NumberField,
+ DateField,
+ BooleanField,
+ ReferenceField,
+ TextInput,
+ DateTimeInput,
+ DateInput,
+ SelectInput,
+ NumberInput,
+ ReferenceInput,
+ ReferenceArrayInput,
+ AutocompleteInput,
+ DeleteButton,
+} from 'react-admin';
+import { Box, Typography, Card, Stack } from '@mui/material';
+import { styled } from '@mui/material/styles';
+import PdaRoleMenuCreate from "./PdaRoleMenuCreate";
+import PdaRoleMenuPanel from "./PdaRoleMenuPanel";
+import EmptyData from "../components/EmptyData";
+import MyCreateButton from "../components/MyCreateButton";
+import MyExportButton from '../components/MyExportButton';
+import PageDrawer from "../components/PageDrawer";
+import MyField from "../components/MyField";
+import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
+import * as Common from '@/utils/common';
+
+const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
+ '& .css-1vooibu-MuiSvgIcon-root': {
+ height: '.9em'
+ },
+ '& .RaDatagrid-row': {
+ cursor: 'auto'
+ },
+ '& .column-name': {
+ },
+ '& .opt': {
+ width: 200
+ },
+}));
+
+const filters = [
+ <SearchInput source="condition" alwaysOn />,
+ <DateInput label='common.time.after' source="timeStart" alwaysOn />,
+ <DateInput label='common.time.before' source="timeEnd" alwaysOn />,
+
+ <NumberInput source="roleId" label="table.field.pdaRoleMenu.roleId" />,
+ <NumberInput source="menuId" label="table.field.pdaRoleMenu.menuId" />,
+
+ <TextInput label="common.field.memo" source="memo" />,
+ <SelectInput
+ label="common.field.status"
+ source="status"
+ choices={[
+ { id: '1', name: 'common.enums.statusTrue' },
+ { id: '0', name: 'common.enums.statusFalse' },
+ ]}
+ resettable
+ />,
+]
+
+const PdaRoleMenuList = () => {
+ const translate = useTranslate();
+
+ const [createDialog, setCreateDialog] = useState(false);
+ const [drawerVal, setDrawerVal] = useState(false);
+
+ return (
+ <Box display="flex">
+ <List
+ sx={{
+ flexGrow: 1,
+ transition: (theme) =>
+ theme.transitions.create(['all'], {
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ }}
+ title={"menu.pdaRoleMenu"}
+ empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
+ filters={filters}
+ sort={{ field: "create_time", order: "desc" }}
+ actions={(
+ <TopToolbar>
+ <FilterButton />
+ <MyCreateButton onClick={() => { setCreateDialog(true) }} />
+ <SelectColumnsButton preferenceKey='pdaRoleMenu' />
+ <MyExportButton />
+ </TopToolbar>
+ )}
+ perPage={DEFAULT_PAGE_SIZE}
+ >
+ <StyledDatagrid
+ preferenceKey='pdaRoleMenu'
+ bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
+ rowClick={(id, resource, record) => false}
+ expand={() => <PdaRoleMenuPanel />}
+ expandSingle={true}
+ omit={['id', 'createTime', 'createBy', 'memo']}
+ >
+ <NumberField source="id" />
+ <NumberField source="roleId" label="table.field.pdaRoleMenu.roleId" />
+ <NumberField source="menuId" label="table.field.pdaRoleMenu.menuId" />
+
+ <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}>
+ <TextField source="nickname" />
+ </ReferenceField>
+ <DateField source="updateTime" label="common.field.updateTime" showTime />
+ <ReferenceField source="createBy" label="common.field.createBy" reference="user" link={false} sortable={false}>
+ <TextField source="nickname" />
+ </ReferenceField>
+ <DateField source="createTime" label="common.field.createTime" showTime />
+ <BooleanField source="statusBool" label="common.field.status" sortable={false} />
+ <TextField source="memo" label="common.field.memo" sortable={false} />
+ <WrapperField cellClassName="opt" label="common.field.opt">
+ <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} />
+ <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
+ </WrapperField>
+ </StyledDatagrid>
+ </List>
+ <PdaRoleMenuCreate
+ open={createDialog}
+ setOpen={setCreateDialog}
+ />
+ <PageDrawer
+ title='PdaRoleMenu Detail'
+ drawerVal={drawerVal}
+ setDrawerVal={setDrawerVal}
+ >
+ </PageDrawer>
+ </Box>
+ )
+}
+
+export default PdaRoleMenuList;
diff --git a/rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuPanel.jsx b/rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuPanel.jsx
new file mode 100644
index 0000000..525ab23
--- /dev/null
+++ b/rsf-admin/src/page/pdaRoleMenu/PdaRoleMenuPanel.jsx
@@ -0,0 +1,63 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material';
+import {
+ useTranslate,
+ useRecordContext,
+} from 'react-admin';
+import PanelTypography from "../components/PanelTypography";
+import * as Common from '@/utils/common'
+
+const PdaRoleMenuPanel = () => {
+ const record = useRecordContext();
+ if (!record) return null;
+ const translate = useTranslate();
+ return (
+ <>
+ <Card sx={{ width: { xs: 300, sm: 500, md: 600, lg: 800 }, margin: 'auto' }}>
+ <CardContent>
+ <Grid container spacing={2}>
+ <Grid item xs={12} sx={{ display: 'flex', justifyContent: 'space-between' }}>
+ <Typography variant="h6" gutterBottom align="left" sx={{
+ maxWidth: { xs: '100px', sm: '180px', md: '260px', lg: '360px' },
+ whiteSpace: 'nowrap',
+ overflow: 'hidden',
+ textOverflow: 'ellipsis',
+ }}>
+ {Common.camelToPascalWithSpaces(translate('table.field.pdaRoleMenu.id'))}: {record.id}
+ </Typography>
+ {/* inherit, primary, secondary, textPrimary, textSecondary, error */}
+ <Typography variant="h6" gutterBottom align="right" >
+ ID: {record.id}
+ </Typography>
+ </Grid>
+ </Grid>
+ <Grid container spacing={2}>
+ <Grid item xs={12} container alignContent="flex-end">
+ <Typography variant="caption" color="textSecondary" sx={{ wordWrap: 'break-word', wordBreak: 'break-all' }}>
+ {Common.camelToPascalWithSpaces(translate('common.field.memo'))}:{record.memo}
+ </Typography>
+ </Grid>
+ </Grid>
+ <Box height={20}> </Box>
+ <Grid container spacing={2}>
+ <Grid item xs={6}>
+ <PanelTypography
+ title="table.field.pdaRoleMenu.roleId"
+ property={record.roleId}
+ />
+ </Grid>
+ <Grid item xs={6}>
+ <PanelTypography
+ title="table.field.pdaRoleMenu.menuId"
+ property={record.menuId}
+ />
+ </Grid>
+
+ </Grid>
+ </CardContent>
+ </Card >
+ </>
+ );
+};
+
+export default PdaRoleMenuPanel;
diff --git a/rsf-admin/src/page/pdaRoleMenu/index.jsx b/rsf-admin/src/page/pdaRoleMenu/index.jsx
new file mode 100644
index 0000000..af3c1fc
--- /dev/null
+++ b/rsf-admin/src/page/pdaRoleMenu/index.jsx
@@ -0,0 +1,18 @@
+import React, { useState, useRef, useEffect, useMemo } from "react";
+import {
+ ListGuesser,
+ EditGuesser,
+ ShowGuesser,
+} from "react-admin";
+
+import PdaRoleMenuList from "./PdaRoleMenuList";
+import PdaRoleMenuEdit from "./PdaRoleMenuEdit";
+
+export default {
+ list: PdaRoleMenuList,
+ edit: PdaRoleMenuEdit,
+ show: ShowGuesser,
+ recordRepresentation: (record) => {
+ return `${record.id}`
+ }
+};
diff --git a/rsf-admin/src/page/system/role/AssignPermissions_pda.jsx b/rsf-admin/src/page/system/role/AssignPermissions_pda.jsx
new file mode 100644
index 0000000..7d6989c
--- /dev/null
+++ b/rsf-admin/src/page/system/role/AssignPermissions_pda.jsx
@@ -0,0 +1,380 @@
+import React, { useState, useRef, useEffect, useMemo, useCallback } from "react";
+import {
+ useTranslate,
+ useNotify,
+ TextInput
+} from 'react-admin';
+import { Box, Button, Card, Stack, CardContent, Skeleton, TextField } from '@mui/material';
+import { SimpleTreeView, TreeItem, RichTreeView, useTreeViewApiRef } from '@mui/x-tree-view';
+import SaveIcon from '@mui/icons-material/Save';
+import request from '@/utils/request'
+
+const DEFAULT_EXPAND_ALL = true;
+
+const AssignPermissionsPda = (props) => {
+ const { role, originMenuIds, setDrawerVal, closeCallback, authType } = props;
+ const translate = useTranslate();
+ const notify = useNotify();
+
+ const [loading, setLoading] = useState(false);
+ const [treeData, setTreeData] = useState([]);
+ const [selectedItems, setSelectedItems] = useState([]);
+ const [expandedItems, setExpandedItems] = useState([]);
+ const [parmas, setParmas] = useState({ condition: '', authType: authType });
+ const toggledItemRef = useRef({});
+ const apiRef = useTreeViewApiRef();
+
+ useEffect(() => {
+ reload()
+ }, [role, originMenuIds])
+
+ const reload = () => {
+ setSelectedItems(originMenuIds.map(item => item + ""));
+
+ const transformTree = (treeData) => {
+ return treeData.map(data => {
+ return {
+ id: data.id + '',
+ label: data.type === 0 ? translate(data.name || data.code) : data.name || data.code,
+ type: data.type,
+ children: (data.children && data.children.length > 0 ? transformTree(data.children) : null)
+ }
+ })
+ }
+ const http = async () => {
+ const res = await request.post('/menuPda/tree', parmas);
+ if (res?.data?.code === 200) {
+ const transformData = transformTree(res.data.data);
+ setTreeData(transformData);
+ if (DEFAULT_EXPAND_ALL) {
+ setExpandedItems(getAllItemsWithChildrenItemIds(transformData));
+ }
+ } else {
+ notify(res.data.msg, { type: 'error' });
+ }
+ setLoading(false);
+ }
+ setLoading(true);
+ setTimeout(() => {
+ http();
+ }, 200);
+ }
+
+
+ const getAllItemItemIds = () => {
+ const ids = [];
+ const registerItemId = (item) => {
+ ids.push(item.id);
+ item.children?.forEach(registerItemId);
+ };
+ treeData.forEach(registerItemId);
+ return ids;
+ };
+
+ const getAllItemsWithChildrenItemIds = (treeDataHandle) => {
+ const itemIds = [];
+ const registerItemId = (item) => {
+ if (item.children?.length) {
+ itemIds.push(item.id);
+ item.children.forEach(registerItemId);
+ }
+ };
+ if (treeDataHandle) {
+ treeDataHandle.forEach(registerItemId);
+ } else {
+ treeData.forEach(registerItemId);
+ }
+ return itemIds;
+ };
+
+ const handleSelectedItemsChange = (event, newSelectedItems) => {
+ const itemsToSelect = [];
+ const itemsToUnSelect = {};
+ Object.entries(toggledItemRef.current).forEach(([itemId, isSelected]) => {
+ const item = apiRef.current.getItem(itemId);
+ if (isSelected) {
+ itemsToSelect.push(...getItemDescendantsIds(item));
+
+ const parentIds = getParentIds(treeData, itemId);
+ itemsToSelect.push(...parentIds);
+ } else {
+ // 鍙栨秷瀛愯妭鐐�
+ const treeNode = checkoutTreeNode(treeData, itemId);
+ if (treeNode?.children && treeNode?.children.length > 0) {
+ const allChildren = getItemDescendantsIds(treeNode);
+ const childrenSet = new Set(allChildren);
+ newSelectedItems = newSelectedItems.filter(item => !childrenSet.has(item));
+ }
+
+ // 鍙栨秷鐖惰妭鐐�
+ const removeParentIfAllSiblingsDeselected = (itemId, newSelectedItems, treeData) => {
+ let updatedSelectedItems = [...newSelectedItems];
+ let currentId = itemId;
+ while (true) {
+ const parentId = getParentId(treeData, currentId);
+ if (!parentId) break;
+ const siblings = getChildrenIds(treeData, parentId);
+ const allSiblingsDeselected = siblings.every(siblingId => !updatedSelectedItems.includes(siblingId));
+ if (allSiblingsDeselected) {
+ updatedSelectedItems = updatedSelectedItems.filter(id => id !== parentId);
+ currentId = parentId;
+ } else {
+ break;
+ }
+ }
+ return updatedSelectedItems;
+ };
+ newSelectedItems = removeParentIfAllSiblingsDeselected(itemId, newSelectedItems, treeData);
+ }
+ });
+
+ const newSelectedItemsWithChildren = Array.from(
+ new Set(
+ [...newSelectedItems, ...itemsToSelect].filter(
+ (itemId) => !itemsToUnSelect[itemId],
+ ),
+ ),
+ );
+
+ setSelectedItems(newSelectedItemsWithChildren);
+
+ toggledItemRef.current = {};
+ };
+
+ const handleSave = (event) => {
+ request.post('/rolePda/scope/update', {
+ id: role.id,
+ menuIds: {
+ checked: selectedItems,
+ halfChecked: []
+ }
+ }).then(res => {
+ if (res?.data.code === 200) {
+ setDrawerVal(null);
+ if (closeCallback) {
+ closeCallback();
+ }
+ notify(res.data.msg, { type: 'info', messageArgs: { _: res.data.msg } })
+ } else {
+ notify(res.data.msg, { type: 'error' })
+ }
+
+ })
+ }
+
+ const search = (e) => {
+ const value = e.target.value;
+ setParmas({
+ ...parmas,
+ condition: value
+ })
+ reload()
+
+ }
+
+ return (
+ <>
+ <Card sx={{
+ ml: 1,
+ mr: 1,
+ height: 'calc(100vh - 140px)',
+ overflowY: 'auto'
+ }}>
+ <CardContent sx={{
+ overflow: 'auto',
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'space-between'
+ }}>
+ <Box>
+ <Box mb={1} sx={{
+ display: 'flex',
+ justifyContent: 'space-between'
+ }}>
+ <Button onClick={() => {
+ setSelectedItems((oldSelected) =>
+ oldSelected.length === 0 ? getAllItemItemIds() : [],
+ );
+ }}>
+ {selectedItems.length === 0 ? translate('ra.action.select_all') : translate('ra.action.unselect')}
+ </Button>
+ <Button onClick={() => {
+ setExpandedItems((oldExpanded) =>
+ oldExpanded.length === 0 ? getAllItemsWithChildrenItemIds() : [],
+ );
+ }}>
+ {expandedItems.length === 0 ? translate('common.action.expandAll') : translate('common.action.collapseAll')}
+ </Button>
+ </Box>
+ <Box sx={{
+ display: 'flex',
+ justifyContent: 'space-between',
+ alignItems: 'center'
+ }}>
+ <TextField sx={{ width: '200px' }} label="鎼滅储鑿滃崟" variant="outlined" value={parmas.condition} onChange={(e) => search(e)} />
+ <Button startIcon={<SaveIcon />} size="small" variant="contained" onClick={handleSave} sx={{ height: '40px' }}>
+ {translate('ra.action.save')}
+ </Button>
+ </Box>
+
+ <Box sx={{
+ minWidth: 290,
+ overflow: 'auto',
+ marginTop: '10px',
+ padding: 1,
+ borderBottom: '1px solid background.paper',
+ borderRadius: '4px',
+ boxShadow: '0 1px 2px rgba(0, 0, 0, 0.2)',
+ backgroundColor: 'background.paper',
+ }}>
+ {loading ? (
+ <SkeletonBox />
+ ) : (
+ <RichTreeView
+ multiSelect
+ checkboxSelection
+ apiRef={apiRef}
+ items={treeData}
+ selectedItems={selectedItems}
+ onSelectedItemsChange={handleSelectedItemsChange}
+ onItemSelectionToggle={(event, itemId, isSelected) => {
+ toggledItemRef.current[itemId] = isSelected;
+ }}
+
+ expandedItems={expandedItems}
+ onExpandedItemsChange={(event, itemIds) => {
+ setExpandedItems(itemIds);
+ }}
+ />
+ )}
+
+ </Box>
+ </Box>
+
+ </CardContent>
+ </Card>
+ </>
+ )
+}
+
+const checkoutTreeNode = (treeData, targetId) => {
+ let result = null;
+ const checkout = (node) => {
+ if (node.id === targetId) {
+ result = node;
+ return true;
+ } else {
+ if (node.children) {
+ for (const child of node.children) {
+ if (checkout(child)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ };
+ treeData.forEach(item => {
+ if (checkout(item)) {
+ return;
+ }
+ });
+ return result;
+};
+
+const getItemDescendantsIds = (item) => {
+ const ids = [];
+ item.children?.forEach((child) => {
+ ids.push(child.id);
+ ids.push(...getItemDescendantsIds(child));
+ });
+ return ids;
+}
+
+const getParentIds = (tree, targetId) => {
+ let parentIds = [];
+ const searchTree = (node, path = []) => {
+ if (node.id === targetId) {
+ parentIds = [...path];
+ return true;
+ }
+ if (node.children) {
+ for (const child of node.children) {
+ if (searchTree(child, [...path, node.id])) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+ tree.forEach(item => {
+ searchTree(item);
+ })
+ return parentIds;
+};
+
+const getParentId = (tree, targetId) => {
+ let parentId = null;
+ const searchTree = (node) => {
+ if (node.children) {
+ for (const child of node.children) {
+ if (child.id === targetId) {
+ parentId = node.id;
+ return true;
+ }
+ if (searchTree(child)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+ tree.forEach(item => {
+ if (searchTree(item)) {
+ return parentId;
+ }
+ });
+ return parentId;
+};
+
+const getChildrenIds = (tree, targetId) => {
+ let childrenIds = [];
+ const searchTree = (node) => {
+ if (node.id === targetId && node.children) {
+ childrenIds = node.children.map(child => child.id);
+ } else if (node.children) {
+ for (const child of node.children) {
+ searchTree(child);
+ }
+ }
+ };
+ tree.forEach(item => {
+ searchTree(item);
+ });
+ return childrenIds;
+};
+
+const SkeletonBox = () => {
+ return (
+ <Stack spacing={1}>
+ <Skeleton variant="rounded" width={200} height={20} />
+ <Skeleton variant="rounded" width={200} height={20} style={{ marginLeft: '50px' }} />
+ <Skeleton variant="rounded" width={200} height={20} style={{ marginLeft: '50px' }} />
+ <Skeleton variant="rounded" width={200} height={20} style={{ marginLeft: '50px' }} />
+ <Skeleton variant="rounded" width={200} height={20} />
+ <Skeleton variant="rounded" width={200} height={20} style={{ marginLeft: '50px' }} />
+ <Skeleton variant="rounded" width={200} height={20} style={{ marginLeft: '50px' }} />
+ <Skeleton variant="rounded" width={200} height={20} style={{ marginLeft: '50px' }} />
+ <Skeleton variant="rounded" width={200} height={20} />
+ <Skeleton variant="rounded" width={200} height={20} style={{ marginLeft: '50px' }} />
+ <Skeleton variant="rounded" width={200} height={20} style={{ marginLeft: '50px' }} />
+ <Skeleton variant="rounded" width={200} height={20} style={{ marginLeft: '50px' }} />
+ <Skeleton variant="rounded" width={200} height={20} />
+ <Skeleton variant="rounded" width={200} height={20} style={{ marginLeft: '50px' }} />
+ <Skeleton variant="rounded" width={200} height={20} style={{ marginLeft: '50px' }} />
+ <Skeleton variant="rounded" width={200} height={20} style={{ marginLeft: '50px' }} />
+ </Stack>
+ )
+}
+
+export default AssignPermissionsPda;
\ No newline at end of file
diff --git a/rsf-admin/src/page/system/role/RoleList.jsx b/rsf-admin/src/page/system/role/RoleList.jsx
index 1973c7d..6ef91f5 100644
--- a/rsf-admin/src/page/system/role/RoleList.jsx
+++ b/rsf-admin/src/page/system/role/RoleList.jsx
@@ -42,8 +42,10 @@
import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import * as Common from '@/utils/common';
import AssignPermissions from "./AssignPermissions";
+import AssignPermissionsPda from "./AssignPermissions_pda";
import request from '@/utils/request';
import AssignmentIndIcon from '@mui/icons-material/AssignmentInd';
+import AdUnitsIcon from '@mui/icons-material/AdUnits';
const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
'& .css-1vooibu-MuiSvgIcon-root': {
@@ -80,10 +82,11 @@
const [createDialog, setCreateDialog] = useState(false);
const [drawerVal, setDrawerVal] = useState(false);
+ const [drawerValPda, setDrawerValPda] = useState(false);
const [menuIds, setMenuIds] = useState([]);
- const [authType,setAuthType] = useState(0)
+ const [authType, setAuthType] = useState(0)
const assign = (record) => {
request('/role/scope/list', {
@@ -102,6 +105,23 @@
});
}
+ const assignPda = (record) => {
+ request('/rolePda/scope/list', {
+ method: 'GET',
+ params: {
+ roleId: record.id
+ }
+ }).then((res) => {
+ if (res?.data?.code === 200) {
+ const { data: menuIds } = res.data;
+ setMenuIds(menuIds || []);
+ setDrawerValPda(!!drawerValPda && drawerValPda === record ? null : record);
+ } else {
+ notify(res.data.msg, { type: 'error' });
+ }
+ });
+ }
+
return (
<Box display="flex">
<List
@@ -111,7 +131,7 @@
theme.transitions.create(['all'], {
duration: theme.transitions.duration.enteringScreen,
}),
- marginRight: !!drawerVal ? `${PAGE_DRAWER_WIDTH}px` : 0,
+ marginRight: (!!drawerVal || !!drawerValPda) ? `${PAGE_DRAWER_WIDTH}px` : 0,
}}
title={"menu.role"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
@@ -131,7 +151,7 @@
preferenceKey='role'
bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
rowClick={(id, resource, record) => false}
- omit={['id', 'createTime', 'memo','statusBool']}
+ omit={['id', 'createTime', 'memo', 'statusBool']}
>
<NumberField source="id" />
<MyField source="name" label="table.field.role.name"
@@ -148,7 +168,7 @@
<TextField source="memo" label="common.field.memo" sortable={false} />
<WrapperField cellClassName="opt" label="common.field.opt">
<ScopeButton sx={{ padding: '1px', fontSize: '.75rem' }} assign={assign} auType={0} setAuthType={setAuthType} label="缃戦〉鏉冮檺 " />
- <ScopeButton sx={{ padding: '1px', fontSize: '.75rem' }} assign={assign} auType={1} setAuthType={setAuthType} label="PDA鏉冮檺 " />
+ <PdaScopeButton sx={{ padding: '1px', fontSize: '.75rem' }} assignPda={assignPda} auType={1} setAuthType={setAuthType} label="PDA鏉冮檺 " />
<ScopeButton sx={{ padding: '1px', fontSize: '.75rem' }} assign={assign} auType={2} setAuthType={setAuthType} label="浠撳簱鏉冮檺 " />
<EditButton sx={{ padding: '1px', fontSize: '.75rem' }} />
<DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
@@ -174,7 +194,25 @@
closeCallback={() => {
setMenuIds([]);
}}
- authType = {authType}
+ authType={authType}
+ />
+ </PageDrawer>
+ <PageDrawer
+ drawerVal={drawerValPda}
+ setDrawerVal={setDrawerValPda}
+ title={!!drawerValPda ? `Scope by ${drawerValPda.code || drawerValPda.name}` : 'Role Detail'}
+ closeCallback={() => {
+ setMenuIds([]);
+ }}
+ >
+ <AssignPermissionsPda
+ role={drawerValPda}
+ originMenuIds={menuIds}
+ setDrawerVal={setDrawerValPda}
+ closeCallback={() => {
+ setMenuIds([]);
+ }}
+ authType={authType}
/>
</PageDrawer>
</Box>
@@ -183,7 +221,7 @@
const ScopeButton = (props) => {
const record = useRecordContext();
- const { assign, auType, setAuthType, label, ...rest } = props;
+ const { assign, auType, setAuthType, label, ...rest } = props;
return (
<Button
variant="text"
@@ -200,4 +238,23 @@
)
}
+const PdaScopeButton = (props) => {
+ const record = useRecordContext();
+ const { assignPda, auType, setAuthType, label, ...rest } = props;
+ return (
+ <Button
+ variant="text"
+ color="primary"
+ startIcon={<AdUnitsIcon />}
+ label={label}
+ onClick={(event) => {
+ setAuthType(auType);
+ event.stopPropagation();
+ assignPda(record);
+ }}
+ {...rest}
+ />
+ )
+}
+
export default RoleList;
diff --git a/rsf-open-api/src/main/resources/application-dev.yml b/rsf-open-api/src/main/resources/application-dev.yml
index f7df34c..c4ba7ad 100644
--- a/rsf-open-api/src/main/resources/application-dev.yml
+++ b/rsf-open-api/src/main/resources/application-dev.yml
@@ -14,8 +14,8 @@
# url: jdbc:mysql://47.76.147.249:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
# username: rsf
username: root
- url: jdbc:mysql://127.0.0.1:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
- password: 34821015
+ url: jdbc:mysql://192.168.4.15:3306/rsf_20250106?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
+ password: 1234
# url: jdbc:mysql://10.10.10.200:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
# password: xltys1995
type: com.alibaba.druid.pool.DruidDataSource
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/InBoundController.java b/rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/InBoundController.java
new file mode 100644
index 0000000..d3a69e6
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/api/controller/pda/InBoundController.java
@@ -0,0 +1,34 @@
+package com.vincent.rsf.server.api.controller.pda;
+
+import com.vincent.rsf.framework.common.R;
+import com.vincent.rsf.server.api.entity.params.PdaGeneralParam;
+import com.vincent.rsf.server.api.service.InBoundService;
+import com.vincent.rsf.server.system.controller.BaseController;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+@Api(tags = "PDA鍏ュ簱鎿嶄綔鎺ュ彛")
+@RequestMapping("/pda")
+@RestController
+public class InBoundController extends BaseController {
+
+ @Autowired
+ private InBoundService inBoundService;
+
+ @PreAuthorize("hasAuthority('manager:task:list')")
+ @PostMapping("/in/emptyContainer/warehousing")
+ @ApiOperation("绌哄鍣ㄥ叆搴�")
+ public R emptyContainerWarehousing(@RequestBody PdaGeneralParam param) {
+
+ return R.ok();
+ }
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/api/entity/params/PdaGeneralParam.java b/rsf-server/src/main/java/com/vincent/rsf/server/api/entity/params/PdaGeneralParam.java
new file mode 100644
index 0000000..0ad33e4
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/api/entity/params/PdaGeneralParam.java
@@ -0,0 +1,15 @@
+package com.vincent.rsf.server.api.entity.params;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@Data
+@Accessors(chain = true)
+public class PdaGeneralParam {
+
+ // 瀹瑰櫒鍙�
+ private String containerNo;
+ // 鎺ラ┏绔欏彿
+ private String transferStationNo;
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/InBoundService.java b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/InBoundService.java
new file mode 100644
index 0000000..927631a
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/InBoundService.java
@@ -0,0 +1,10 @@
+package com.vincent.rsf.server.api.service;
+
+import com.vincent.rsf.framework.common.R;
+
+/**
+ * PDA鍏ュ簱鎿嶄綔Service鎺ュ彛
+ */
+public interface InBoundService {
+
+}
\ No newline at end of file
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/InBoundServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/InBoundServiceImpl.java
new file mode 100644
index 0000000..4ce52c2
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/api/service/impl/InBoundServiceImpl.java
@@ -0,0 +1,14 @@
+package com.vincent.rsf.server.api.service.impl;
+
+import com.vincent.rsf.server.api.service.InBoundService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+/**
+ * PDA鍏ュ簱鎿嶄綔Service瀹炵幇绫�
+ */
+@Slf4j
+@Service
+public class InBoundServiceImpl implements InBoundService {
+
+}
\ No newline at end of file
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
index e8bbef4..cd880a0 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/CodeBuilder.java
@@ -15,15 +15,15 @@
generator.frontendPrefixPath = "rsf-admin/";
generator.sqlOsType = SqlOsType.MYSQL;
- generator.url = "192.168.4.151:3306/rsf";
+ generator.url = "192.168.4.15:3306/rsf_20250106";
generator.username = "root";
- generator.password = "34821015";
+ generator.password = "1234";
// generator.url="47.97.1.152:51433;databasename=jkasrs";
// generator.username="sa";
// generator.password="Zoneyung@zy56$";
- generator.table = "view_stock_statistic";
- generator.tableDesc = "鏃ュ簱瀛樼粺璁�";
+ generator.table = "sys_pda_role_menu";
+ generator.tableDesc = "PDA鏉冮檺";
generator.packagePath = "com.vincent.rsf.server.manager";
generator.build();
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/common/config/MybatisPlusConfig.java b/rsf-server/src/main/java/com/vincent/rsf/server/common/config/MybatisPlusConfig.java
index 70da919..056b4a7 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/common/config/MybatisPlusConfig.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/common/config/MybatisPlusConfig.java
@@ -52,6 +52,8 @@
"sys_user_role",
"sys_role_menu",
"sys_menu",
+ "sys_pda_role_menu",
+ "sys_menu_pda",
"man_loc_type_rela",
"man_qly_inspect_result",
"view_stock_manage",
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MenuPdaController.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MenuPdaController.java
new file mode 100644
index 0000000..e46fcd6
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/controller/MenuPdaController.java
@@ -0,0 +1,157 @@
+package com.vincent.rsf.server.manager.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.vincent.rsf.common.utils.Utils;
+import com.vincent.rsf.framework.common.Cools;
+import com.vincent.rsf.framework.common.R;
+import com.vincent.rsf.server.common.utils.ExcelUtil;
+import com.vincent.rsf.server.common.annotation.OperationLog;
+import com.vincent.rsf.server.common.domain.BaseParam;
+import com.vincent.rsf.server.common.domain.KeyValVo;
+import com.vincent.rsf.server.common.domain.PageParam;
+import com.vincent.rsf.server.common.utils.NodeUtils;
+import com.vincent.rsf.server.manager.entity.MenuPda;
+import com.vincent.rsf.server.manager.service.MenuPdaService;
+import com.vincent.rsf.server.system.controller.BaseController;
+import com.vincent.rsf.server.system.entity.Menu;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.*;
+
+@RestController
+public class MenuPdaController extends BaseController {
+
+ @Autowired
+ private MenuPdaService menuPdaService;
+
+ @PreAuthorize("hasAuthority('manager:menuPda:list')")
+ @PostMapping("/menuPda/page")
+ public R page(@RequestBody Map<String, Object> map) {
+ BaseParam baseParam = buildParam(map, BaseParam.class);
+ PageParam<MenuPda, BaseParam> pageParam = new PageParam<>(baseParam, MenuPda.class);
+ return R.ok().add(menuPdaService.page(pageParam, pageParam.buildWrapper(true)));
+ }
+
+ @PreAuthorize("hasAuthority('manager:menuPda:list')")
+ @PostMapping("/menuPda/list")
+ public R list(@RequestBody Map<String, Object> map) {
+ return R.ok().add(menuPdaService.list());
+ }
+
+ @PreAuthorize("hasAuthority('manager:menuPda:list')")
+ @PostMapping({"/menuPda/many/{ids}", "/menuPdas/many/{ids}"})
+ public R many(@PathVariable Long[] ids) {
+ return R.ok().add(menuPdaService.listByIds(Arrays.asList(ids)));
+ }
+
+ @PreAuthorize("hasAuthority('manager:menuPda:list')")
+ @GetMapping("/menuPda/{id}")
+ public R get(@PathVariable("id") Long id) {
+ return R.ok().add(menuPdaService.getById(id));
+ }
+
+// @PreAuthorize("hasAuthority('system:menu:list')")
+ @PostMapping("/menuPda/tree")
+ public R tree(@RequestBody Map<String, Object> map) {
+// PageParam<Menu, BaseParam> param = new PageParam<>(buildParam(map, BaseParam.class), Menu.class);
+// QueryWrapper<Menu> wrapper = param.buildWrapper(true, queryWrapper -> queryWrapper.orderByAsc("sort"));
+// List<Menu> menus = menuService.list(wrapper);
+// return R.ok().add(Utils.toTreeData(menus, 0L, Menu::getParentId, Menu::getId, Menu::setChildren));
+ List<MenuPda> menuList = menuPdaService.list(new LambdaQueryWrapper<MenuPda>().orderByAsc(MenuPda::getSort));
+ List<MenuPda> treeData = Utils.toTreeData(menuList, 0L, MenuPda::getParentId, MenuPda::getId, MenuPda::setChildren);
+ if (!Cools.isEmpty(map.get("condition"))) {
+ Utils.treeRemove(treeData, String.valueOf(map.get("condition")), MenuPda::getName, MenuPda::getChildren);
+ Utils.treeRemove(treeData, String.valueOf(map.get("condition")), MenuPda::getName, MenuPda::getChildren);
+ }
+ return R.ok().add(treeData);
+ }
+
+ @PreAuthorize("hasAuthority('system:menu:save')")
+ @OperationLog("Save Menu")
+ @PostMapping("/menuPda/save")
+ public R save(@RequestBody MenuPda menu) {
+ if (menu.getParentId() != null && menu.getParentId() > 0) {
+ MenuPda parent = menuPdaService.getById(menu.getParentId());
+ if (parent != null) {
+ menu.setParentName(parent.getName());
+ }
+ } else {
+ menu.setParentId(0L);
+ }
+
+ NodeUtils nodeUtils = new NodeUtils();
+ nodeUtils.generatePath0(item -> menuPdaService.getById(item.getParentId()), menu, MenuPda::getId, MenuPda::getName, MenuPda::getParentId);
+ menu.setPath(nodeUtils.path.toString());
+ menu.setPathName(nodeUtils.pathName.toString());
+
+ menu.setCreateBy(getLoginUserId());
+ menu.setCreateTime(new Date());
+ menu.setUpdateBy(getLoginUserId());
+ menu.setUpdateTime(new Date());
+ if (!menuPdaService.save(menu)) {
+ return R.error("Save Fail");
+ }
+ return R.ok("Save Success").add(menu);
+ }
+
+ @PreAuthorize("hasAuthority('system:menu:update')")
+ @OperationLog("Update Menu")
+ @PostMapping("/menuPda/update")
+ public R update(@RequestBody MenuPda menu) {
+ if (menu.getParentId() != null && menu.getParentId() > 0) {
+ MenuPda parent = menuPdaService.getById(menu.getParentId());
+ if (parent != null) {
+ menu.setParentName(parent.getName());
+ }
+ } else {
+ menu.setParentId(0L);
+ }
+
+ NodeUtils nodeUtils = new NodeUtils();
+ nodeUtils.generatePath0(item -> menuPdaService.getById(item.getParentId()), menu, MenuPda::getId, MenuPda::getName, MenuPda::getParentId);
+ menu.setPath(nodeUtils.path.toString());
+ menu.setPathName(nodeUtils.pathName.toString());
+
+ menu.setUpdateBy(getLoginUserId());
+ menu.setUpdateTime(new Date());
+ if (!menuPdaService.updateById(menu)) {
+ return R.error("Update Fail");
+ }
+ return R.ok("Update Success").add(menu);
+ }
+
+ @PreAuthorize("hasAuthority('manager:menuPda:remove')")
+ @OperationLog("Delete PDA鏉冮檺")
+ @PostMapping("/menuPda/remove/{ids}")
+ public R remove(@PathVariable Long[] ids) {
+ if (!menuPdaService.removeByIds(Arrays.asList(ids))) {
+ return R.error("Delete Fail");
+ }
+ return R.ok("Delete Success").add(ids);
+ }
+
+ @PreAuthorize("hasAuthority('manager:menuPda:list')")
+ @PostMapping("/menuPda/query")
+ public R query(@RequestParam(required = false) String condition) {
+ List<KeyValVo> vos = new ArrayList<>();
+ LambdaQueryWrapper<MenuPda> wrapper = new LambdaQueryWrapper<>();
+ if (!Cools.isEmpty(condition)) {
+ wrapper.like(MenuPda::getName, condition);
+ }
+ menuPdaService.page(new Page<>(1, 30), wrapper).getRecords().forEach(
+ item -> vos.add(new KeyValVo(item.getId(), item.getName()))
+ );
+ return R.ok().add(vos);
+ }
+
+ @PreAuthorize("hasAuthority('manager:menuPda:list')")
+ @PostMapping("/menuPda/export")
+ public void export(@RequestBody Map<String, Object> map, HttpServletResponse response) throws Exception {
+ ExcelUtil.build(ExcelUtil.create(menuPdaService.list(), MenuPda.class), response);
+ }
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/MenuPda.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/MenuPda.java
new file mode 100644
index 0000000..e16825f
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/entity/MenuPda.java
@@ -0,0 +1,258 @@
+package com.vincent.rsf.server.manager.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.vincent.rsf.server.system.entity.Menu;
+import com.vincent.rsf.server.system.entity.Tenant;
+import com.vincent.rsf.server.system.service.TenantService;
+import org.springframework.format.annotation.DateTimeFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import com.vincent.rsf.framework.common.Cools;
+import com.vincent.rsf.framework.common.SpringUtils;
+import com.vincent.rsf.server.system.service.UserService;
+import com.vincent.rsf.server.system.entity.User;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+@Data
+@TableName("sys_menu_pda")
+public class MenuPda implements Serializable, GrantedAuthority {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final int TYPE_MENU = 0; // 鑿滃崟绫诲瀷
+ public static final int TYPE_BTN = 1; // 鎸夐挳绫诲瀷
+
+ /**
+ * ID
+ */
+ @ApiModelProperty(value = "ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ /**
+ * 鍚嶇О
+ */
+ @ApiModelProperty(value = "鍚嶇О")
+ private String name;
+
+ /**
+ * 涓婄骇鑿滃崟
+ */
+ @ApiModelProperty(value = "涓婄骇鑿滃崟")
+ private Long parentId;
+
+ /**
+ * 涓婄骇鑿滃崟鍚�
+ */
+ @ApiModelProperty(value = "涓婄骇鑿滃崟鍚�")
+ private String parentName;
+
+ /**
+ * 鍏宠仈璺緞
+ */
+ @ApiModelProperty(value = "鍏宠仈璺緞")
+ private String path;
+
+ /**
+ * 鍏宠仈璺緞鍚�
+ */
+ @ApiModelProperty(value = "鍏宠仈璺緞鍚�")
+ private String pathName;
+
+ /**
+ * 璺敱鍦板潃
+ */
+ @ApiModelProperty(value = "璺敱鍦板潃")
+ private String route;
+
+ /**
+ * 椤甸潰缁勪欢
+ */
+ @ApiModelProperty(value = "椤甸潰缁勪欢")
+ private String component;
+
+ /**
+ * 绠�杩�
+ */
+ @ApiModelProperty(value = "绠�杩�")
+ private String brief;
+
+ /**
+ * 鏍囪瘑
+ */
+ @ApiModelProperty(value = "鏍囪瘑")
+ private String code;
+
+ /**
+ * 绫诲瀷 0: 鑿滃崟 1: 鎸夐挳
+ */
+ @ApiModelProperty(value = "绫诲瀷 0: 鑿滃崟 1: 鎸夐挳 ")
+ private Integer type;
+
+ /**
+ * 鏉冮檺鏍囪瘑
+ */
+ @ApiModelProperty(value = "鏉冮檺鏍囪瘑")
+ private String authority;
+
+ /**
+ * 鑿滃崟鍥炬爣
+ */
+ @ApiModelProperty(value = "鑿滃崟鍥炬爣")
+ private String icon;
+
+ /**
+ * 鎺掑簭
+ */
+ @ApiModelProperty(value = "鎺掑簭")
+ private Integer sort;
+
+ /**
+ * 鍏冧俊鎭�
+ */
+ @ApiModelProperty(value = "鍏冧俊鎭�")
+ private String meta;
+
+ /**
+ * 鎵�灞炴満鏋�
+ */
+ @ApiModelProperty(value = "鎵�灞炴満鏋�")
+ private Long tenantId;
+
+ /**
+ * 鐘舵�� 1: 姝e父 0: 绂佺敤
+ */
+ @ApiModelProperty(value = "鐘舵�� 1: 姝e父 0: 绂佺敤 ")
+ private Integer status;
+
+ /**
+ * 鏄惁鍒犻櫎 1: 鏄� 0: 鍚�
+ */
+ @ApiModelProperty(value = "鏄惁鍒犻櫎 1: 鏄� 0: 鍚� ")
+ @TableLogic
+ private Integer deleted;
+
+ /**
+ * 娣诲姞鏃堕棿
+ */
+ @ApiModelProperty(value = "娣诲姞鏃堕棿")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private Date createTime;
+
+ /**
+ * 娣诲姞浜哄憳
+ */
+ @ApiModelProperty(value = "娣诲姞浜哄憳")
+ private Long createBy;
+
+ /**
+ * 淇敼鏃堕棿
+ */
+ @ApiModelProperty(value = "淇敼鏃堕棿")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+ private Date updateTime;
+
+ /**
+ * 淇敼浜哄憳
+ */
+ @ApiModelProperty(value = "淇敼浜哄憳")
+ private Long updateBy;
+
+ /**
+ * 澶囨敞
+ */
+ @ApiModelProperty(value = "澶囨敞")
+ private String memo;
+
+ @TableField(exist = false)
+ private List<MenuPda> children;
+
+ public MenuPda() {
+ }
+
+ public String getType$() {
+ if (null == this.type) {
+ return null;
+ }
+ switch (this.type) {
+ case 0:
+ return "鑿滃崟";
+ case 1:
+ return "鎸夐挳";
+ default:
+ return String.valueOf(this.type);
+ }
+ }
+
+ public String getTenantId$() {
+ TenantService service = SpringUtils.getBean(TenantService.class);
+ Tenant tenant = service.getById(this.tenantId);
+ if (!Cools.isEmpty(tenant)) {
+ return String.valueOf(tenant.getName());
+ }
+ return null;
+ }
+
+ public String getCreateTime$() {
+ if (Cools.isEmpty(this.createTime)) {
+ return "";
+ }
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.createTime);
+ }
+
+ public String getCreateBy$() {
+ UserService service = SpringUtils.getBean(UserService.class);
+ User user = service.getById(this.createBy);
+ if (!Cools.isEmpty(user)) {
+ return String.valueOf(user.getNickname());
+ }
+ return null;
+ }
+
+ public String getUpdateTime$() {
+ if (Cools.isEmpty(this.updateTime)) {
+ return "";
+ }
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(this.updateTime);
+ }
+
+ public String getUpdateBy$() {
+ UserService service = SpringUtils.getBean(UserService.class);
+ User user = service.getById(this.updateBy);
+ if (!Cools.isEmpty(user)) {
+ return String.valueOf(user.getNickname());
+ }
+ return null;
+ }
+
+ public Boolean getStatusBool() {
+ if (null == this.status) {
+ return null;
+ }
+ switch (this.status) {
+ case 1:
+ return true;
+ case 0:
+ return false;
+ default:
+ return null;
+ }
+ }
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/MenuPdaMapper.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/MenuPdaMapper.java
new file mode 100644
index 0000000..464428c
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/mapper/MenuPdaMapper.java
@@ -0,0 +1,12 @@
+package com.vincent.rsf.server.manager.mapper;
+
+import com.vincent.rsf.server.manager.entity.MenuPda;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.springframework.stereotype.Repository;
+
+@Mapper
+@Repository
+public interface MenuPdaMapper extends BaseMapper<MenuPda> {
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/CheckOrderSchedules.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/CheckOrderSchedules.java
index 12938da..18b8ada 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/CheckOrderSchedules.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/CheckOrderSchedules.java
@@ -1,6 +1,5 @@
package com.vincent.rsf.server.manager.schedules;
-
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.exception.CoolException;
import com.vincent.rsf.server.manager.entity.*;
@@ -70,13 +69,16 @@
return;
}
Long loginUserId = SystemAuthUtils.getLoginUserId();
- Map<Long, List<TaskItem>> taskMps = taskItems.stream().collect(Collectors.groupingBy(TaskItem::getOrderId));
+ Map<Long, List<TaskItem>> taskMps = taskItems.stream()
+ .filter(item -> Objects.nonNull(item.getOrderId()))
+ .collect(Collectors.groupingBy(TaskItem::getOrderId));
taskMps.keySet().forEach(orderId -> {
WkOrder order = checkOrderService.getById(orderId);
if (Objects.isNull(order)) {
throw new CoolException("鐩樼偣鍗曟嵁涓嶅瓨鍦紒锛�");
}
- CheckDiff checkDiff = checkDiffService.getOne(new LambdaQueryWrapper<CheckDiff>().eq(CheckDiff::getOrderId, orderId));
+ CheckDiff checkDiff = checkDiffService
+ .getOne(new LambdaQueryWrapper<CheckDiff>().eq(CheckDiff::getOrderId, orderId));
if (Objects.isNull(checkDiff)) {
checkDiff = new CheckDiff();
checkDiff.setAnfme(order.getAnfme())
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
index eb5e75e..061473a 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/schedules/TaskSchedules.java
@@ -237,7 +237,7 @@
/**
* 闈炲厜鐢电珯鐐逛换鍔′笅鍙�
*/
- @Scheduled(cron = "0/5 * * * * ? ")
+// @Scheduled(cron = "0/5 * * * * ? ")
@Transactional(rollbackFor = Exception.class)
public void pubTaskToWcs() {
Long loginUserId = SystemAuthUtils.getLoginUserId();
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/MenuPdaService.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/MenuPdaService.java
new file mode 100644
index 0000000..ea61403
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/MenuPdaService.java
@@ -0,0 +1,8 @@
+package com.vincent.rsf.server.manager.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.vincent.rsf.server.manager.entity.MenuPda;
+
+public interface MenuPdaService extends IService<MenuPda> {
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/MenuPdaServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/MenuPdaServiceImpl.java
new file mode 100644
index 0000000..b184894
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/manager/service/impl/MenuPdaServiceImpl.java
@@ -0,0 +1,12 @@
+package com.vincent.rsf.server.manager.service.impl;
+
+import com.vincent.rsf.server.manager.mapper.MenuPdaMapper;
+import com.vincent.rsf.server.manager.entity.MenuPda;
+import com.vincent.rsf.server.manager.service.MenuPdaService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+@Service("menuPdaService")
+public class MenuPdaServiceImpl extends ServiceImpl<MenuPdaMapper, MenuPda> implements MenuPdaService {
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/PdaRoleMenuController.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/PdaRoleMenuController.java
new file mode 100644
index 0000000..325b1b4
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/PdaRoleMenuController.java
@@ -0,0 +1,58 @@
+package com.vincent.rsf.server.system.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.vincent.rsf.framework.common.Cools;
+import com.vincent.rsf.framework.common.R;
+import com.vincent.rsf.framework.exception.CoolException;
+import com.vincent.rsf.server.common.utils.ExcelUtil;
+import com.vincent.rsf.server.common.annotation.OperationLog;
+import com.vincent.rsf.server.common.domain.BaseParam;
+import com.vincent.rsf.server.common.domain.KeyValVo;
+import com.vincent.rsf.server.common.domain.PageParam;
+import com.vincent.rsf.server.system.controller.param.RoleScopeParam;
+import com.vincent.rsf.server.system.entity.PdaRoleMenu;
+import com.vincent.rsf.server.system.entity.Role;
+import com.vincent.rsf.server.system.entity.RoleMenu;
+import com.vincent.rsf.server.system.service.PdaRoleMenuService;
+import com.vincent.rsf.server.system.controller.BaseController;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.*;
+
+@RestController
+public class PdaRoleMenuController extends BaseController {
+
+ @Autowired
+ private PdaRoleMenuService pdaRoleMenuService;
+
+// @PreAuthorize("hasAuthority('system:role:list')")
+ @GetMapping("/rolePda/scope/list")
+ public R scopeList(@RequestParam Long roleId) {
+ return R.ok().add(pdaRoleMenuService.listStrictlyMenuByRoleId(roleId));
+ }
+
+ @PreAuthorize("hasAuthority('system:role:update')")
+ @OperationLog("Assign Permissions")
+ @PostMapping("/rolePda/scope/update")
+ @Transactional
+ public R scopeUpdate(@RequestBody RoleScopeParam param) {
+ Long roleId = param.getId();
+ List<Long> menuIds = new ArrayList<>(param.getMenuIds().getChecked());
+ menuIds.addAll(param.getMenuIds().getHalfChecked());
+ pdaRoleMenuService.remove(new LambdaQueryWrapper<PdaRoleMenu>().eq(PdaRoleMenu::getRoleId, roleId));
+ for (Long menuId : menuIds) {
+ if (!pdaRoleMenuService.save(new PdaRoleMenu(roleId, menuId))) {
+ throw new CoolException("Internal Server Error!");
+ }
+ }
+ return R.ok("Assign Success");
+ }
+
+
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/entity/PdaRoleMenu.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/entity/PdaRoleMenu.java
new file mode 100644
index 0000000..5b10d4e
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/entity/PdaRoleMenu.java
@@ -0,0 +1,50 @@
+package com.vincent.rsf.server.system.entity;
+
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import com.vincent.rsf.framework.common.Cools;
+import com.vincent.rsf.framework.common.SpringUtils;
+import com.vincent.rsf.server.system.service.UserService;
+import com.vincent.rsf.server.system.entity.User;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@TableName("sys_pda_role_menu")
+public class PdaRoleMenu implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @ApiModelProperty(value= "")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Long id;
+
+ @ApiModelProperty(value= "")
+ private Long roleId;
+
+ @ApiModelProperty(value= "")
+ private Long menuId;
+
+ public PdaRoleMenu() {}
+
+ public PdaRoleMenu(Long roleId,Long menuId) {
+ this.roleId = roleId;
+ this.menuId = menuId;
+ }
+
+// PdaRoleMenu pdaRoleMenu = new PdaRoleMenu(
+// null, // [闈炵┖]
+// null // [闈炵┖]
+// );
+
+
+
+
+
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/mapper/PdaRoleMenuMapper.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/mapper/PdaRoleMenuMapper.java
new file mode 100644
index 0000000..d3b21a3
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/mapper/PdaRoleMenuMapper.java
@@ -0,0 +1,22 @@
+package com.vincent.rsf.server.system.mapper;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.vincent.rsf.server.manager.entity.MenuPda;
+import com.vincent.rsf.server.system.entity.Menu;
+import com.vincent.rsf.server.system.entity.PdaRoleMenu;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+@Mapper
+@Repository
+public interface PdaRoleMenuMapper extends BaseMapper<PdaRoleMenu> {
+
+ @InterceptorIgnore(tenantLine = "true")
+ List<MenuPda> listMenuByUserId(@Param("userId") Long userId, @Param("type") Integer menuType);
+
+ List<Long> listStrictlyMenuByRoleId(@Param("roleId") Long roleId);
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/service/PdaRoleMenuService.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/service/PdaRoleMenuService.java
new file mode 100644
index 0000000..c5b43bd
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/service/PdaRoleMenuService.java
@@ -0,0 +1,14 @@
+package com.vincent.rsf.server.system.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.vincent.rsf.server.manager.entity.MenuPda;
+import com.vincent.rsf.server.system.entity.Menu;
+import com.vincent.rsf.server.system.entity.PdaRoleMenu;
+
+import java.util.List;
+
+public interface PdaRoleMenuService extends IService<PdaRoleMenu> {
+ List<MenuPda> listMenuByUserId(Long userId, Integer menuType);
+
+ List<Long> listStrictlyMenuByRoleId(Long roleId);
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/service/impl/PdaRoleMenuServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/service/impl/PdaRoleMenuServiceImpl.java
new file mode 100644
index 0000000..6168ed1
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/service/impl/PdaRoleMenuServiceImpl.java
@@ -0,0 +1,24 @@
+package com.vincent.rsf.server.system.service.impl;
+
+import com.vincent.rsf.server.manager.entity.MenuPda;
+import com.vincent.rsf.server.system.entity.Menu;
+import com.vincent.rsf.server.system.mapper.PdaRoleMenuMapper;
+import com.vincent.rsf.server.system.entity.PdaRoleMenu;
+import com.vincent.rsf.server.system.service.PdaRoleMenuService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service("pdaRoleMenuService")
+public class PdaRoleMenuServiceImpl extends ServiceImpl<PdaRoleMenuMapper, PdaRoleMenu> implements PdaRoleMenuService {
+ @Override
+ public List<MenuPda> listMenuByUserId(Long userId, Integer menuType) {
+ return baseMapper.listMenuByUserId(userId, menuType);
+ }
+
+ @Override
+ public List<Long> listStrictlyMenuByRoleId(Long roleId) {
+ return baseMapper.listStrictlyMenuByRoleId(roleId);
+ }
+}
diff --git a/rsf-server/src/main/java/menuPda.sql b/rsf-server/src/main/java/menuPda.sql
new file mode 100644
index 0000000..d381644
--- /dev/null
+++ b/rsf-server/src/main/java/menuPda.sql
@@ -0,0 +1,35 @@
+-- save menuPda record
+-- mysql
+insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.menuPda', '0', '/manager/menuPda', 'menuPda', '0' , '0', '1' , '1');
+
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query PDA鏉冮檺', '', '1', 'manager:menuPda:list', '0', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create PDA鏉冮檺', '', '1', 'manager:menuPda:save', '1', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update PDA鏉冮檺', '', '1', 'manager:menuPda:update', '2', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete PDA鏉冮檺', '', '1', 'manager:menuPda:remove', '3', '1', '1');
+
+-- locale menu name
+menuPda: 'MenuPda',
+
+-- locale field
+menuPda: {
+ name: "name",
+ parentId: "parentId",
+ parentName: "parentName",
+ path: "path",
+ pathName: "pathName",
+ route: "route",
+ component: "component",
+ brief: "brief",
+ code: "code",
+ type: "type",
+ authority: "authority",
+ icon: "icon",
+ sort: "sort",
+ meta: "meta",
+},
+
+-- ResourceContent
+import menuPda from './menuPda';
+
+case 'menuPda':
+ return menuPda;
diff --git a/rsf-server/src/main/java/pdaRoleMenu.sql b/rsf-server/src/main/java/pdaRoleMenu.sql
new file mode 100644
index 0000000..c977da7
--- /dev/null
+++ b/rsf-server/src/main/java/pdaRoleMenu.sql
@@ -0,0 +1,23 @@
+-- save pdaRoleMenu record
+-- mysql
+insert into `sys_menu` ( `name`, `parent_id`, `route`, `component`, `type`, `sort`, `tenant_id`, `status`) values ( 'menu.pdaRoleMenu', '0', '/system/pdaRoleMenu', 'pdaRoleMenu', '0' , '0', '1' , '1');
+
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Query PDA鏉冮檺', '', '1', 'system:pdaRoleMenu:list', '0', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Create PDA鏉冮檺', '', '1', 'system:pdaRoleMenu:save', '1', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Update PDA鏉冮檺', '', '1', 'system:pdaRoleMenu:update', '2', '1', '1');
+insert into `sys_menu` ( `name`, `parent_id`, `type`, `authority`, `sort`, `tenant_id`, `status`) values ( 'Delete PDA鏉冮檺', '', '1', 'system:pdaRoleMenu:remove', '3', '1', '1');
+
+-- locale menu name
+pdaRoleMenu: 'PdaRoleMenu',
+
+-- locale field
+pdaRoleMenu: {
+ roleId: "roleId",
+ menuId: "menuId",
+},
+
+-- ResourceContent
+import pdaRoleMenu from './pdaRoleMenu';
+
+case 'pdaRoleMenu':
+ return pdaRoleMenu;
diff --git a/rsf-server/src/main/resources/application-dev.yml b/rsf-server/src/main/resources/application-dev.yml
index b4140cf..b3bcadf 100644
--- a/rsf-server/src/main/resources/application-dev.yml
+++ b/rsf-server/src/main/resources/application-dev.yml
@@ -16,7 +16,7 @@
username: root
# url: jdbc:mysql://10.10.10.200:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
# password: xltys1995
- url: jdbc:mysql://192.168.4.15:3306/rsf?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
+ url: jdbc:mysql://192.168.4.15:3306/rsf_20250106?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
password: 1234
type: com.alibaba.druid.pool.DruidDataSource
druid:
diff --git a/rsf-server/src/main/resources/mapper/manager/MenuPdaMapper.xml b/rsf-server/src/main/resources/mapper/manager/MenuPdaMapper.xml
new file mode 100644
index 0000000..157aacc
--- /dev/null
+++ b/rsf-server/src/main/resources/mapper/manager/MenuPdaMapper.xml
@@ -0,0 +1,5 @@
+<?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.vincent.rsf.server.manager.mapper.MenuPdaMapper">
+
+</mapper>
diff --git a/rsf-server/src/main/resources/mapper/system/PdaRoleMenuMapper.xml b/rsf-server/src/main/resources/mapper/system/PdaRoleMenuMapper.xml
new file mode 100644
index 0000000..5ab2813
--- /dev/null
+++ b/rsf-server/src/main/resources/mapper/system/PdaRoleMenuMapper.xml
@@ -0,0 +1,37 @@
+<?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.vincent.rsf.server.system.mapper.PdaRoleMenuMapper">
+ <select id="listMenuByUserId" resultType="com.vincent.rsf.server.manager.entity.MenuPda">
+ SELECT DISTINCT sm.*
+ FROM sys_menu_pda sm
+ JOIN sys_pda_role_menu srm ON sm.id = srm.menu_id
+ JOIN sys_user_role sur ON srm.role_id = sur.role_id
+ JOIN sys_role sr ON sur.role_id = sr.id
+ WHERE 1=1
+ <if test="type != null">
+ AND sm.type = #{type}
+ </if>
+ AND sur.user_id = #{userId}
+ AND sr.deleted = 0
+ AND sm.deleted = 0
+ ORDER BY sm.sort
+ </select>
+
+ <select id="listStrictlyMenuByRoleId" resultType="java.lang.Long">
+ select sm.id
+ from sys_menu_pda sm
+ left join sys_pda_role_menu srm on sm.id = srm.menu_id
+ where 1=1
+ and sm.deleted = 0
+ and srm.role_id = #{roleId}
+ <!--
+ and sm.id not in (
+ select sm.parent_id
+ from sys_menu sm
+ inner join sys_role_menu srm on sm.id = srm.menu_id
+ and srm.role_id = #{roleId}
+ )
+ -->
+ order by sm.sort
+ </select>
+</mapper>
--
Gitblit v1.9.1