app-base-web
Version:
web development common base package.
642 lines (618 loc) • 17.9 kB
JavaScript
import React from 'react';
import {Layout, Tree, Table, Form, Row, Col, Button, Input, InputNumber, message, Modal} from 'antd'
import UtilModal from '../../../library/util-modal';
import UtilDic from '../../../library/util-dic';
import UtilString from '../../../library/util-string';
import Jquery from '../../../library/jquery';
import Dic from '../../../library/dic';
import api from '../../../library/util-axios';
import EditTable from '../../../library/editTable';
// 系统管理-菜单管理
const title = "菜单管理"
const url = "SysMenu/"
class SysMenuList extends React.Component {
constructor(props) {
super(props)
this.state = {
params: {
parentId: this.props.parentId,
parentName: this.props.parentName
},
data: [],
pagination: {},
loading: false,
selected: [],//Table checked
//显藏控制
showView: false,
showEdit: false,
//values
values: {},
}
this.columns = [{
title: "序号",
width: 50,
fixed: "left",
render: (text, record, index) => {
return index + 1
}
}, {
title: "菜单ID",
dataIndex: "id",
width: 50,
render: (text, record) => (<a className="btn-detail" onClick={() => this.onView(record)}>{text}</a>)
}, {
title: "菜单名称",
dataIndex: "name",
width: 200,
render: (text, record) => (<a className="btn-detail" onClick={() => this.onView(record)}>{text}</a>)
},
{
title: "上级菜单名称",
dataIndex: "parentName",
width: 200
},
{
title: "菜单类型",
dataIndex: "type",
width: 100,
render: (text, record) => {
return UtilDic.json("app", "菜单类型")[text]
}
},
{
title: "样式",
dataIndex: "className",
width: 100
},
{
title: "图标",
dataIndex: "imgSrc",
width: 100
},
{
title: "参数",
dataIndex: "params",
width: 150
},
{
title: "接口权限",
dataIndex: "permission",
width: 150
},
{
title: "顺序号",
dataIndex: "ord",
width: 60
}]
}
componentDidMount() {
this.onLoad(this.state.params)
}
/*** Table ***/
async onLoad(params) {
this.setState({loading: true})
let rs = await api.get(url + "getList", params)
let pagination = {
pageSizeOptions: ["20", "100", "200", "500", "1000"],
pageSize: params.pageSize || 20,
defaultPageSize: params.pageSize || 20,
showSizeChanger: true,
showQuickJumper: true,
total: rs.total,
showTotal: (total) => {
return `总记录 ${total} `
}
}
this.setState({
loading: false,
showEdit: false,
params,
data: rs.data,
pagination,
})
}
onChange = (pagination, filters, sorter) => {
let params = this.state.params
params.pageSize = pagination.pageSize
params.pageIndex = pagination.current
this.onLoad(params)
}
onSearch = (value) => {
let params = this.state.params
params.name = value
this.onLoad(params)
}
onAdd = () => {
let values = {}
Object.keys(this.state.values).forEach(key => values[key] = undefined)
values.parentId = this.state.params.parentId
values.parentName = this.state.params.parentName
this.setState({
showView: false,
showEdit: true,
values
})
}
onCopy = () => {
let me = this;
if (me.state.selected.length == 0) {
message.error('请选择记录!');
return;
}
api.post(url + "copy", me.state.selected).then(function (rs) {
if (rs.success) {
message.info(rs.msg);
me.onLoad(me.state.params || {});
} else { message.error(rs.msg); }
});
}
onView = (values) => {
this.setState({
showView: true,
loading: false,
values
})
}
onEdit = (values) => {
let me = this
api.get(url + "getModel?id=" + values.id, {}, function (rs) {
me.setState({
showEdit: true,
showView: false,
values: rs.data
})
})
}
onSave = (values) => {
this.onLoad(this.state.params)
if(this.props.onSave){
this.props.onSave()
}
}
onDel = () => {
let me = this;
if (me.state.selected.length == 0) {
message.error('请选择记录!');
return;
}
UtilModal.confirm({
content: '确定删除?',
onOk: function () {
api.post(url + "delete?id=" + me.state.selected).then(function (rs) {
if (rs.success) {
message.info(rs.msg)
me.onLoad(me.state.params || {})
if(me.props.onSave){
me.props.onSave()
}
} else {
message.error(rs.msg)
}
});
}
})
}
render() {
var tableCfg = {
scroll: {y: this.props.height - 210},
size: "middle",
rowKey: "id",
columns: this.columns,
rowSelection: {
selectedRowKeys: this.state.selected,
onChange: (selectedRowKeys, selectedRows) => {
this.setState({
selected: selectedRowKeys
})
}
},
rowClassName: (record) => {
return record.id === this.state.selectedRowId ? 'row-selected' : ''
},
onRow: (record) => {
return {
onClick: event => {
this.setState({selectedRowId: record.id})
}
}
},
dataSource: this.state.data,
pagination: this.state.pagination,
loading: this.state.loading,
onChange: this.onChange
}
return <div className="app-admin">
<div className={this.state.showView || this.state.showEdit ? "hide" : ""}>
<Row>
<Col className="main-title"><i className="iconfont icon-title"></i>{title}</Col>
</Row>
<Row className="main-toolbar">
<Col className="text-left" xs={16}>
<Button className="btn-add" onClick={this.onAdd}><i className="iconfont icon-add"></i>录入</Button>
<Button className="btn-copy" onClick={this.onCopy}><i className="iconfont icon-copy"></i>拷贝</Button>
<Button className="btn-del" onClick={this.onDel}><i className="iconfont icon-del"></i>删除</Button>
</Col>
<Col className="text-right" xs={8}>
<Input.Search placeholder="请输入名称" onSearch={value => this.onSearch(value)} enterButton/>
</Col>
</Row>
<Table {...tableCfg} />
</div>
{this.state.showView ? <FormView
height={this.props.height - 140}
values={this.state.values}
onEdit={this.onEdit}
onReturn={() => {
this.setState({showView: false})
}}
/> : ""}
{this.state.showEdit ? <FormEdit
height={this.props.height - 140}
values={this.state.values}
onSave={this.onSave}
onCancel={() => {
this.setState({showEdit: false})
}}
onEditReturn={() => {
this.setState({showEdit: false, showView: true})
}}
/> : ""}
</div>
}
}
class MenuTree extends React.Component {
constructor(props) {
super(props)
this.state = {
value: undefined,
label: undefined,
treeData: [],
treeKey:UtilString.uuid()
}
this.initData()
}
async initData() {
let rs = await api.post("SysMenu/listTreeMenu", {})
this.setState({treeData: rs.data.treeData, defaultExpandedKeys: rs.data.defaultExpandedKeys, treeKey: UtilString.uuid()})
}
onSelect = (selectedKeys, e) => {
this.props.onSetParent(e.node.props.id, e.node.props.title)
}
render() {
return (<Tree
autoExpandParent={true}
blockNode={true}
checkable={false}
treeData={this.state.treeData}
defaultExpandAll={true}
defaultExpandParent={true}
defaultExpandedKeys={this.state.defaultExpandedKeys}
showLine={true}
draggable={true}
selectable={true}
onSelect={this.onSelect}
key={this.state.treeKey}
/>)
}
}
export default class SysMenu extends React.Component {
constructor(props) {
super(props)
this.state = {
parentId: -1,
parentName: "",
menuKey: UtilString.uuid(),
menuTreeKey: UtilString.uuid(),
isShowMenu:false
}
}
onSetParent = (parentId, parentName) => {
this.setState({
parentId,
parentName,
menuKey: UtilString.uuid(),
isShowMenu: true
})
}
componentDidMount() {
let timer = setInterval(function () {
let el = Jquery(".ant-tree-iconEle")
if (el.length > 0) {
el.remove()
clearInterval(timer)
}
}, 100)
}
onSave = ()=>{
this.setState({
menuTreeKey:UtilString.uuid()
})
}
render() {
return <Layout style={{background: "#f0f2f5", height: "100%"}}>
<Layout.Sider theme="light" width="200" style={{padding: "15px 20px", marginRight: "10px"}}>
<MenuTree onSetParent={this.onSetParent} key={this.state.menuTreeKey}/>
</Layout.Sider>
<Layout.Content style={{background: "#fff", paddingLeft: "20px"}}>
{this.state.isShowMenu
?
<SysMenuList key={this.state.menuKey} parentId={this.state.parentId} parentName={this.state.parentName} onSave={this.onSave}/>
:
"请选择主菜单"
}
</Layout.Content>
</Layout>
}
}
class FormView extends React.Component {
constructor(props) {
super(props)
this.state = {
...props.values
}
}
componentDidMount() {
let me = this
api.get(url + "getModel?id=" + this.state.id, {}, function (rs) {
me.setState({
...rs.data
})
})
}
render() {
return (
<Form className="form-view">
<div className="form-title">
<i>{title} - 详情</i>
<span><Button className="btn-edit" onClick={(e) => {
this.props.onEdit(this.state)
}}><i className="iconfont icon-edit"></i>编辑</Button></span>
</div>
<div className="form-content" style={{height: this.props.height}}>
<Row>
<Col xs={24}><label>上级菜单名称</label><span>{this.state.parentName}</span></Col>
</Row>
<Row>
<Col xs={24}><label>菜单ID</label><span>{this.state.id}</span></Col>
</Row>
<Row>
<Col xs={24}><label>菜单名称</label><span>{this.state.name}</span></Col>
</Row>
<Row>
<Col xs={24}><label>菜单类型</label><span>{UtilDic.json("app", "菜单类型")[this.state.type]}</span></Col>
</Row>
<Row>
<Col xs={24}><label>样式</label><span>{this.state.className}</span></Col>
</Row>
<Row>
<Col xs={24}><label>图标</label><span>{this.state.imgSrc}</span></Col>
</Row>
<Row>
<Col xs={24}><label>参数</label><span>{this.state.params}</span></Col>
</Row>
<Row>
<Col xs={24}><label>接口权限</label><span>{this.state.permission}</span></Col>
</Row>
<Row>
<Col xs={24}><label>顺序号</label><span>{this.state.ord}</span></Col>
</Row>
</div>
<div className="form-toolbar">
<Button className="btn-return" onClick={this.props.onReturn}><i
className="iconfont icon-return"></i>返回</Button>
</div>
</Form>
)
}
}
class FormEdit extends React.Component {
constructor(props) {
super(props)
this.state = {
...props.values
}
this.formRef = React.createRef()
}
onSave = (values) => {
let me = this
values.id = this.state.id
values.parentId = this.state.parentId
if(this.state.params){
values.params = this.state.params
}
api.post(url + "save", values).then(function (rs) {
if (rs.success) {
message.info(rs.msg)
me.props.onSave(values)
} else {
message.error(rs.msg)
}
})
//todo 应该通过redux来处理多级层级想回通讯
if(this.props.onSave){
this.props.onSave()
}
}
//控制模态框
showModal = () => {
//将对象转换成数组
let dataSource = []
let params = this.state.params
if(params&¶ms.trim()!=''){
params = JSON.parse(params)
for(let key in params){
let obj = {}
obj['paramKey'] = key
obj['paramValue'] = params[key]
dataSource.push(obj)
}
}
this.setState({
visible: true,
dataSource
})
}
handleOk = e => {
console.log(e)
let params = {}
let dataSource = this.refs.params.state.dataSource
if (dataSource) {
//循环取值
dataSource.map((item, index) => {
let paramKey = item.paramKey
let paramValue = item.paramValue
if (paramKey && paramKey.trim() != '') {
params[paramKey] = paramValue
}
})
if (JSON.stringify(params) != "{}") {
this.setState({
params:JSON.stringify(params)
})
}
}
this.setState({
visible: false,
})
}
handleCancel = e => {
console.log(e)
this.setState({
visible: false,
})
}
render() {
return (
<div>
<Modal
title="添加参数"
visible={this.state.visible}
onOk={this.handleOk}
onCancel={this.handleCancel}
width={700}
>
<EditTable ref='params' dataSource={this.state.dataSource}/>
</Modal>
<Form ref={this.formRef} className="form-edit" layout="vertical" onFinish={this.onSave}>
<div className="form-title">
<i> {title} - {this.state.id ? "编辑" : "录入"}</i>
{this.state.id ? <span><Button className="btn-return" onClick={this.props.onEditReturn}><i
className="iconfont icon-return"></i>返回</Button></span> : ""}
</div>
<div className="form-content" style={{height: this.props.height}}>
<Row>
<Col xs={24}>
<Form.Item
name="parentName"
label="父级菜单"
initialValue={this.state.parentName}
>
<Input disabled/>
</Form.Item>
</Col>
</Row>
<Row>
<Col xs={24}>
<Form.Item
name="name"
label="菜单名称"
initialValue={this.state.name}
rules={[{
required: true,
message: '请输入菜单名称'
}]}
>
<Input/>
</Form.Item>
</Col>
</Row>
<Row>
<Col xs={24}>
<Form.Item
name="type"
label="菜单类型"
initialValue={this.state.type}
rules={[{
required: true,
message: '请输入菜单类型'
}]}
>
<Dic params={{app: "app", type: "菜单类型"}}/>
</Form.Item>
</Col>
</Row>
<Row>
<Col xs={24}>
<Form.Item
name="className"
label="样式"
initialValue={this.state.className}
>
<Input/>
</Form.Item>
</Col>
</Row>
<Row>
<Col xs={24}>
<Form.Item
name="imgSrc"
label="图标"
initialValue={this.state.imgSrc}
>
<Input/>
</Form.Item>
</Col>
</Row>
<Row>
<Col xs={24}>
<Form.Item
name="params"
label="参数"
initialValue={this.state.params}
>
<div style={{display: 'flex'}}>
<Input.TextArea disabled={true} value={this.state.params}/>
<Button onClick={this.showModal} className="btn-add" icon={<i className="iconfont icon-add"></i>}>
添加参数
</Button>
</div>
</Form.Item>
</Col>
</Row>
<Row>
<Col xs={24}>
<Form.Item
name="permission"
label="接口权限"
initialValue={this.state.permission}
>
<Input/>
</Form.Item>
</Col>
</Row>
<Row>
<Col xs={24}>
<Form.Item
name="ord"
label="顺序号"
initialValue={this.state.ord}
rules={[{
required: true,
message: '请输入顺序号'
}]}
>
<InputNumber style={{width: "100%"}}/>
</Form.Item>
</Col>
</Row>
</div>
<div className="form-toolbar">
<Button className="btn-cancel" onClick={this.props.onCancel}><i
className="iconfont icon-cancel"></i>取消</Button>
<Button className="btn-submit" htmlType="submit"><i className="iconfont icon-submit"></i>提交</Button>
</div>
</Form>
</div>
)
}
}