菜单接口

main
expressgy 1 year ago
parent cc77d3465a
commit 477986c61a
  1. 3
      package-lock.json
  2. 3
      package.json
  3. 11
      src/main.jsx
  4. 330
      src/pages/Edit/index.jsx
  5. 77
      src/pages/Edit/index.module.scss
  6. 47
      src/request/api/edit.js
  7. 45
      src/request/index.js
  8. 25
      vite.config.js

3
package-lock.json generated

@ -8,6 +8,7 @@
"name": "myamis",
"version": "0.0.0",
"dependencies": {
"@ant-design/icons": "^5.1.4",
"@fortawesome/fontawesome-free": "^5.15.3",
"amis": "3.1.1",
"amis-core": "3.1.1",
@ -16,7 +17,7 @@
"amis-formula": "3.1.1",
"amis-ui": "3.1.1",
"antd": "^5.6.2",
"axios": "0.21.1",
"axios": "^0.21.1",
"copy-to-clipboard": "^3.2.0",
"mobx": "4.15.7",
"mobx-react": "6.3.1",

@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@ant-design/icons": "^5.1.4",
"@fortawesome/fontawesome-free": "^5.15.3",
"amis": "3.1.1",
"amis-core": "3.1.1",
@ -18,7 +19,7 @@
"amis-formula": "3.1.1",
"amis-ui": "3.1.1",
"antd": "^5.6.2",
"axios": "0.21.1",
"axios": "^0.21.1",
"copy-to-clipboard": "^3.2.0",
"mobx": "4.15.7",
"mobx-react": "6.3.1",

@ -23,12 +23,17 @@ import './scss/style.scss';
import {setDefaultTheme} from 'amis';
import 'antd/dist/reset.css';
import { BrowserRouter } from "react-router-dom";
import zhCN from 'antd/locale/zh_CN';
import {ConfigProvider} from 'antd'
setDefaultTheme('cxd');
// react < 18
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>, document.getElementById('root'));
<ConfigProvider locale={zhCN}>
<BrowserRouter>
<App />
</BrowserRouter>
</ConfigProvider>
, document.getElementById('root'));
// node -v 18.16.0

@ -1,10 +1,252 @@
import {Editor} from 'amis-editor'
import { useEffect } from 'react';
import css from './index.module.scss'
import { useEffect, useState } from 'react';
import css from './index.module.scss';
import { PlusOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons'
import { Modal, Form, Input, Button, message, Menu, Popconfirm } from 'antd'
import api from '../../request/api/edit'
export default function Edit(){
//
const [reflush, setReflush] = useState(true)
//
const [menuTree, setMenuTree] = useState([])
//
const [menuList, setMenuList] = useState([])
//
const [atomMenuList, setAtomMenuList] = useState([])
const [nowMenuItemId, setNowMenuItemId] = useState('')
useEffect(() => {
console.log('EDIT')
})
api.getMenu().then(
resd => {
if(resd.data.code == 200){
setMenuList(formateMenuToList([...resd.data.data]))
setAtomMenuList([...resd.data.data])
}else{
messageApi.open({
type: 'error',
content: '获取菜单失败!',
});
}
}
)
}, [reflush])
useEffect(() => {
const list = formateMenuList(atomMenuList)
setMenuTree(list)
}, [atomMenuList])
//
const [messageApi, contextHolder] = message.useMessage();
//
const [openKeys, setOpenKeys] = useState([]);
//
const [ menuParentId, setMenuParentId] = useState(null)
//
const [isModalOpenForCreateMneu, setIsModalOpenForCreateMneu] = useState(false);
//
const [isModalOpenForEditMneu, setIsModalOpenForEditMneu] = useState(false);
//
const [ createMenuForm ] = Form.useForm();
const [ editMenuForm ] = Form.useForm();
//
const showModalForCreateMneu = () => {
setIsModalOpenForCreateMneu(true);
};
//
const handleOkForCreateMneu = () => {
createMenuForm.submit()
};
//
const handleCancelForCreateMneu = () => {
setIsModalOpenForCreateMneu(false);
setMenuParentId(null)
};
//
const editMenu = key => {
console.log(key)
console.log(menuList, menuTree)
const data = menuList.find(item => {
// console.log(item)
return item.id == key
})
setNowMenuItemId(data.id)
editMenuForm.setFieldsValue({
name : data.name,
value: data.value
})
setIsModalOpenForEditMneu(true)
}
//
const handleOkForEditMneu = () => {
editMenuForm.submit()
};
//
const handleCancelForEditMneu = () => {
setIsModalOpenForEditMneu(false);
};
//
const onOpenChange = (keys) => {
const latestOpenKey = keys.find((key) => openKeys.indexOf(key) === -1);
setOpenKeys(latestOpenKey ? [latestOpenKey] : []);
// console.log(keys)
// if (rootSubmenuKeys.indexOf(latestOpenKey) === -1) {
// setOpenKeys(keys);
// } else {
//
// }
};
//
function onSelectMenu(val){
// console.log(val)
setNowMenuItemId(val.key)
};
//
function deleteMenuItem(id){
api.deleteMenuItem(id).then(
resd => {
if(resd.data.code == 200){
messageApi.open({
type: 'success',
content: '删除菜单成功!',
});
}else{
messageApi.open({
type: 'error',
content: '删除菜单失败!',
});
}
setReflush(!reflush)
}
)
};
//
function createSonMenu(key){
showModalForCreateMneu()
setMenuParentId(key)
};
//
function formateMenuList(list){
const newList = []
for(let i in list){
const item = list[i];
const newItem = {
key: item.id.toString(),
label: <div className={css.menuItem}>
<div title={item.name}>{item.name}</div>
<div>
<span onClick={() => createSonMenu(item.id.toString())}>
<Button type="ghost" icon={<PlusOutlined />} size={'small'}/>
</span>
<span onClick={() => editMenu(item.id.toString())}>
<Button type="ghost" icon={<EditOutlined />} size={'small'}/>
</span>
<span >
<Popconfirm
title="删除目录"
description="去人要删除当前目录吗?"
onConfirm={() => deleteMenuItem(item.id.toString())}
>
<Button danger type="text" icon={<DeleteOutlined />} size={'small'}/>
</Popconfirm>
</span></div></div>,
data: item
}
if(item.childrenList){
newItem.children = formateMenuList(item.childrenList)
}
newList.push(newItem)
}
return newList
};
function formateMenuToList(list){
const newList = []
list.map(item => {
const now = {...item}
if(item.childrenList){
const sonList = formateMenuToList(item.childrenList)
newList.push(...sonList)
delete now.childrenList
}
newList.push(now)
})
return newList
}
//
const onFinishForCreateMenu = (values ) => {
const { name, value} = values
api.createMenu({
name, value, parentId: menuParentId ? menuParentId : 0
}).then(
resd => {
console.log(resd.data)
if(resd.data.code == 200){
console.log('添加成功')
messageApi.open({
type: 'success',
content: '添加菜单成功!',
});
handleCancelForCreateMneu();
createMenuForm.resetFields();
setReflush(!reflush)
}else{
messageApi.open({
type: 'error',
content: resd.data.msg,
});
}
}
)
};
//
const onFinishFailedForCreateMenu = (errorInfo ) => {
// console.log('Failed:', errorInfo);
};
//
const onFinishForEditMenu = (values ) => {
const { name, value} = values
const nowMenuItem = menuList.find(item => item.id == nowMenuItemId)
const parentId = nowMenuItem.parentId
const id = nowMenuItemId
api.editMenu({
name, value, parentId, id
}).then(
resd => {
if(resd.data.code == 200){
messageApi.open({
type: 'success',
content: '编辑菜单成功!',
});
setIsModalOpenForEditMneu(false);
editMenuForm.resetFields();
setReflush(!reflush)
}else{
messageApi.open({
type: 'error',
content: resd.data.msg,
});
}
}
)
};
//
const onFinishFailedForEditMenu = (errorInfo ) => {
// console.log('Failed:', errorInfo);
};
const data = {
value:{},
onChange: (value ) => {
@ -13,13 +255,91 @@ export default function Edit(){
}
return (
<div className={css.main}>
<div className={css.left}></div>
<div className={css.left}>
<header>
<div onClick={showModalForCreateMneu}><PlusOutlined />添加主菜单</div>
</header>
<div className={css.body}>
<Menu
mode="inline"
openKeys={openKeys}
onOpenChange={onOpenChange}
style={{ width: 200 }}
onSelect={onSelectMenu}
items={menuTree}
/>
</div>
</div>
<div className={css.right}>
<div className="Editor-Demo">
<div className="Editor-header"></div>
<Editor value={data.value} onChange={data.onChange}/>
</div>
</div>
{contextHolder}
<Modal title="添加菜单" open={isModalOpenForCreateMneu} onOk={handleOkForCreateMneu} onCancel={handleCancelForCreateMneu}>
<div>
<Form
name="basic"
labelCol={{ span: 5 }}
wrapperCol={{ span: 18 }}
style={{ maxWidth: 600 }}
initialValues={{ remember: true }}
onFinish={onFinishForCreateMenu}
onFinishFailed={onFinishFailedForCreateMenu}
autoComplete="off"
form={ createMenuForm }
>
<Form.Item
label="菜单名称"
name="name"
rules={[{ required: true, max: 20, message: '请输入菜单名称!' }]}
>
<Input placeholder='限制20个字符' maxLength={20}/>
</Form.Item>
<Form.Item
label="路径名称"
name="value"
rules={[
{ required: true, message: '请输入菜单路径!' },
{ max: 20, pattern: new RegExp(/^[a-zA-Z]+$/), message: '请输入字母!' }]}>
<Input placeholder='限制20个字符' maxLength={20} />
</Form.Item>
</Form>
</div>
</Modal>
<Modal title="编辑菜单" open={isModalOpenForEditMneu} onOk={handleOkForEditMneu} onCancel={handleCancelForEditMneu}>
<div>
<Form
name="basic"
labelCol={{ span: 5 }}
wrapperCol={{ span: 18 }}
style={{ maxWidth: 600 }}
initialValues={{ remember: true }}
onFinish={onFinishForEditMenu}
onFinishFailed={onFinishFailedForEditMenu}
autoComplete="off"
form={ editMenuForm }
>
<Form.Item
label="菜单名称"
name="name"
rules={[{ required: true, max: 20, message: '请输入菜单名称!' }]}
>
<Input placeholder='限制20个字符' maxLength={20}/>
</Form.Item>
<Form.Item
label="路径名称"
name="value"
rules={[
{ required: true, message: '请输入菜单路径!' },
{ max: 20, pattern: new RegExp(/^[a-zA-Z]+$/), message: '请输入字母!' }]}>
<Input placeholder='限制20个字符' maxLength={20} />
</Form.Item>
</Form>
</div>
</Modal>
</div>
)
}

@ -1,19 +1,64 @@
.main{
position: relative;
height: 100%;
display: flex;
overflow: hidden;
& > div{
.main {
position: relative;
}
& > div.left{
height: 100%;
flex-shrink: 0;
width: 200px;
border-right: 1px solid #cdcdcd;
}
& > div.right{
height: 100%;
flex:1;
}
display: flex;
overflow: hidden;
& > div {
position: relative;
}
& > div.left {
height: 100%;
flex-shrink: 0;
width: 220px;
border-right: 1px solid #cdcdcd;
display: flex;
flex-direction: column;
padding: 10px;
& > header {
position: relative;
flex-shrink: 0;
height: 40px;
& > div{
position: relative;
border-radius: 10px;
background: #2468f2;
padding: 0.5em 1em;
color: #fefefe;
text-align: center;
cursor: pointer;
&:hover{
}
}
}
& > div.menu{
position: relative;
flex: 1;
overflow: auto;
}
}
& > div.right {
height: 100%;
flex: 1;
}
}
.menuItem{
position: relative;
display: flex;
overflow: hidden;
& > div:first-child{
flex:1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
& > div:last-child{
flex-shrink: 0;
}
}

@ -0,0 +1,47 @@
// 合同管理和合同审批相关 接口文件
import request from '../index'
const agreementApi = {
// 添加菜单
createMenu: data => request({
url: '/jiaSheng/homeMenu/add',
method: 'post',
data: data
}),
getMenu: () => request({
url: '/jiaSheng/homeMenu/getList',
method: 'get'
}),
deleteMenuItem: id => request({
url: `/jiaSheng/homeMenu/${id}`,
method: 'delete',
}),
// 编辑菜单
editMenu: data => request({
url: '/jiaSheng/homeMenu/update',
method: 'put',
data: data
}),
// 获取 可发起 流程列表
getApproveListPage: data => request({
url: `/flowable/process/list`,
method: 'get',
params: data
}),
//保存合同 /agreement/agreement/add
addAgreement: data => request({
url: `/flowable/agreement/add`,
method: 'post',
data: data
}),
// 删除流程
deleteProcessPage: data => request({
url: `/flowable/task/delete`,
method: 'delete',
data: data
}),
}
export default agreementApi

@ -0,0 +1,45 @@
import axios from "axios";
/* axios默认配置*/
const instance = axios.create({
timeout: 20000,
baseURL: "/api", // 服务器请求地址
});
/* 请求方式 默认请求头的 Content-Type */
instance.defaults.headers.post["Content-Type"] =
"application/json;charset=UTF-8";
instance.defaults.headers.delete["Content-Type"] =
"application/json;charset=UTF-8";
instance.defaults.headers.put["Content-Type"] =
"application/json;charset=UTF-8";
/* 整理数据,序列化为 JSON*/
instance.defaults.transformRequest = function (data) {
if (data && data.NOSERI) {
return data.data;
} else {
return JSON.stringify(data);
}
};
/* Request 拦截器*/
instance.interceptors.request.use((config) => {
// 加载动画
/* 添加token */
if(config.url.split('/')[1] && config.url.split('/')[1] == 'source'){
config.baseURL = '/api/resource'
}
if(config.url.split('/')[1] && config.url.split('/')[1] == 'work'){
config.baseURL = '/api/works'
}
if (config.url=='/system/user/getInfo'){
config.baseURL = '/api'
}
const token=window.localStorage.getItem('token')||window.sessionStorage.getItem('token')
config.headers["Authorization"] ="Bearer "+token;
return config;
});
export default instance;

@ -1,7 +1,32 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import {
fileURLToPath,
URL
} from 'node:url'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src',
import.meta.url))
}
},
server: {
host: "0.0.0.0",
proxy: {
'/api': {
// target: "http://10.10.10.107:9208",// 目标地址
target: `http://10.10.10.168:8080`,// sar目标地址
// target: `http://10.10.10.200/api/`,// 测试服务器址
// target: "http://10.10.10.146:9309",// Rock目标地址
// target: `http://togy.top:18080/api/`,// sar目标地址
ws: true,// 开始ws代理
changeOrigin: true, // 开发模式
rewrite: (path) => path.replace(/^\/api/, "")
},
}
},
})

Loading…
Cancel
Save