482 lines
14 KiB
JavaScript
482 lines
14 KiB
JavaScript
|
|
// 核心库
|
|||
|
|
import React from 'react'
|
|||
|
|
// 组件库
|
|||
|
|
import { message, Button, Icon, Popconfirm, Empty } from 'antd'
|
|||
|
|
import { Search, OrganizationTree } from '@woowalker/feui'
|
|||
|
|
import ComponentBase from "../ComponentBase"
|
|||
|
|
import Node from "./node"
|
|||
|
|
import VPage from './VPage'
|
|||
|
|
import EditModal from '../../components/Edit/EditModal'
|
|||
|
|
import CombinationModal from '../../components/Combination/CombinationModal'
|
|||
|
|
import TableModal from '../../components/Table/TableModal'
|
|||
|
|
import FormModal from '../../components/FormModal'
|
|||
|
|
import DataLoading from '../../components/common/DataLoading'
|
|||
|
|
// 工具库
|
|||
|
|
import { cloneDeep } from 'lodash'
|
|||
|
|
import { addRuleAndGroups, extendRule, extendGroupRule, initFilter } from "../../utils/common"
|
|||
|
|
// 样式
|
|||
|
|
import styles from '../Component.css'
|
|||
|
|
let formParam = ''
|
|||
|
|
class TreeBaseComponent extends ComponentBase {
|
|||
|
|
constructor (props) {
|
|||
|
|
super(props)
|
|||
|
|
this.state = {
|
|||
|
|
data: {},
|
|||
|
|
treeConfig: {},
|
|||
|
|
treeLoadParam: {},
|
|||
|
|
showAdd: false,
|
|||
|
|
showModal: false
|
|||
|
|
}
|
|||
|
|
this.defaultTreeCode = 'tree'
|
|||
|
|
};
|
|||
|
|
componentDidMount () {
|
|||
|
|
super.componentDidMount()
|
|||
|
|
this.onLoadData()
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
componentWillReceiveProps (NextProps) {
|
|||
|
|
super.componentWillReceiveProps(NextProps)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
onLoadTreeData ({ treeCode, searchValue, onComplete }) {
|
|||
|
|
const treeConfig = this.getTreeConfig({ treeCode })
|
|||
|
|
if (treeConfig) {
|
|||
|
|
const { sort, order, relationField, relationId, api, orgType, ignoreOrgRule } = treeConfig
|
|||
|
|
|
|||
|
|
if (!api) return
|
|||
|
|
const treeLoadParam = this.state.treeLoadParam
|
|||
|
|
let loadParam = treeLoadParam[treeCode]
|
|||
|
|
|
|||
|
|
if (!loadParam) {
|
|||
|
|
loadParam = initFilter(this.props.login.OrgId, '', sort, order)
|
|||
|
|
treeLoadParam[treeCode] = loadParam
|
|||
|
|
}
|
|||
|
|
loadParam['Level'] = -1
|
|||
|
|
const rules = this.props && this.props.data && this.props.data.rules ? this.props.data.rules : []
|
|||
|
|
const json = cloneDeep(loadParam)
|
|||
|
|
|
|||
|
|
formParam = this.props.formParam
|
|||
|
|
if (formParam) {
|
|||
|
|
for (var val in formParam) {
|
|||
|
|
json[val] = formParam[val]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (rules) {
|
|||
|
|
rules.forEach(item => {
|
|||
|
|
extendRule(json, item.field, item.operator, item.value, item.isSysParam)
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
if (orgType) {
|
|||
|
|
json.OrgType = orgType
|
|||
|
|
}
|
|||
|
|
if (searchValue) {
|
|||
|
|
addRuleAndGroups(json, searchValue)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//填加关联字段过滤
|
|||
|
|
if (relationField && relationId) {
|
|||
|
|
extendRule(json, relationField, 1, relationId)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 是否忽略组织权限
|
|||
|
|
if (ignoreOrgRule) {
|
|||
|
|
json.IgnoreOrgRule = ignoreOrgRule
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//配置的自定义查询条件
|
|||
|
|
if (this.props.data?.Filter) {
|
|||
|
|
json[this.props.data.Filter] = this.props.data.ID
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 配置的自定义过滤参数
|
|||
|
|
if (this.props.data?.customParams) {
|
|||
|
|
extendGroupRule(json.FilterGroup, this.props.data.customParams, 1, this.props.data.ID)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.props.dispatch({
|
|||
|
|
type: 'app/getTableData',
|
|||
|
|
payload: json,
|
|||
|
|
url: api,
|
|||
|
|
onComplete: (ret) => {
|
|||
|
|
if (ret) {
|
|||
|
|
if (!ret.IsSuccessful) {
|
|||
|
|
message.error(ret.ErrorMessage)
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
const datas = JSON.stringify(ret.Data)
|
|||
|
|
this.setTreeData({
|
|||
|
|
treeCode,
|
|||
|
|
data: JSON.parse(datas.toLowerCase()),
|
|||
|
|
onComplete,
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
获取树配置
|
|||
|
|
*/
|
|||
|
|
getTreeConfig (params) {
|
|||
|
|
const { treeCode = this.defaultTreeCode } = params ? params : {}
|
|||
|
|
let treeConfig = this.state.treeConfig
|
|||
|
|
if (!treeConfig) {
|
|||
|
|
treeConfig = {}
|
|||
|
|
}
|
|||
|
|
return treeConfig[treeCode]
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
设置树配置
|
|||
|
|
*/
|
|||
|
|
setTreeConfig (params) {
|
|||
|
|
const { treeConfig, onComplete } = params ? params : {}
|
|||
|
|
let tempTreeConfig = this.state.treeConfig
|
|||
|
|
if (!tempTreeConfig) {
|
|||
|
|
tempTreeConfig = {}
|
|||
|
|
}
|
|||
|
|
if (treeConfig.treeCode === undefined) {
|
|||
|
|
treeConfig.treeCode = this.defaultTreeCode
|
|||
|
|
}
|
|||
|
|
tempTreeConfig = {
|
|||
|
|
...tempTreeConfig,
|
|||
|
|
[treeConfig.treeCode]: treeConfig,
|
|||
|
|
}
|
|||
|
|
this.setState({
|
|||
|
|
treeConfig: tempTreeConfig
|
|||
|
|
}, () => {
|
|||
|
|
if (typeof onComplete === 'function') {
|
|||
|
|
onComplete()
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
获取树数据
|
|||
|
|
*/
|
|||
|
|
getTreeData (params) {
|
|||
|
|
const { treeCode = this.defaultTreeCode } = params ? params : {}
|
|||
|
|
let data = this.state.treeData
|
|||
|
|
if (!data) {
|
|||
|
|
data = {}
|
|||
|
|
}
|
|||
|
|
return data[treeCode]
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
设置树数据
|
|||
|
|
*/
|
|||
|
|
setTreeData ({ treeCode, data, onComplete }) {
|
|||
|
|
let tempData = this.state.treeData
|
|||
|
|
if (!tempData) {
|
|||
|
|
tempData = {}
|
|||
|
|
}
|
|||
|
|
if (treeCode === undefined) {
|
|||
|
|
treeCode = this.defaultTreeCode
|
|||
|
|
}
|
|||
|
|
tempData = {
|
|||
|
|
...tempData,
|
|||
|
|
[treeCode]: data,
|
|||
|
|
}
|
|||
|
|
this.setState({
|
|||
|
|
treeData: tempData,
|
|||
|
|
}, () => {
|
|||
|
|
if (typeof onComplete === 'function') {
|
|||
|
|
onComplete()
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 节点包含MENU_LEVEL:第几级(没有默认第一个颜色),ICON:下方图标(没有默认不显示)
|
|||
|
|
*/
|
|||
|
|
MyNode = (data) => {
|
|||
|
|
const treeCode = this.defaultTreeCode
|
|||
|
|
const treeConfig = this.getTreeConfig({ treeCode })
|
|||
|
|
return (
|
|||
|
|
<Node
|
|||
|
|
key={`${data.node.id}--customNode`}
|
|||
|
|
treeCode={treeCode}
|
|||
|
|
treeConfig={treeConfig}
|
|||
|
|
treePicFilter={this.state.picFilter}
|
|||
|
|
nodeData={data}
|
|||
|
|
{...this.props}
|
|||
|
|
showModal={this.state.showModal}
|
|||
|
|
getRenderBtn={this.getRenderBtn} />
|
|||
|
|
)
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
click = visible => {
|
|||
|
|
this.setState({ showModal: visible })
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
getRenderBtn = (params = {}) => {
|
|||
|
|
const { record, btnConfig = {} } = params
|
|||
|
|
// 编辑 新增 查看 复制新增 新增同级
|
|||
|
|
if (
|
|||
|
|
btnConfig.btnType === 5
|
|||
|
|
|| btnConfig.btnType === 3
|
|||
|
|
|| btnConfig.btnType === 8
|
|||
|
|
|| btnConfig.btnType === 10
|
|||
|
|
|| (btnConfig.btnType === -1 && record.parent_id)
|
|||
|
|
) {
|
|||
|
|
const isShow = btnConfig.btnType === 8
|
|||
|
|
|
|||
|
|
const isBatchEdit = false
|
|||
|
|
const extKey = record ? (record.id + btnConfig.id) : btnConfig.id
|
|||
|
|
const reloadKey = this.props.formCode + '_' + extKey + '_reload'
|
|||
|
|
const data = {
|
|||
|
|
isShow: isShow,
|
|||
|
|
record: record || {},
|
|||
|
|
isBatchEdit,
|
|||
|
|
reloadKey,
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
if (this.props.data?.Filter) {
|
|||
|
|
data.record[this.props.data.Filter] = this.props.data.ID
|
|||
|
|
}
|
|||
|
|
const extraSaveData = {}
|
|||
|
|
if (this.props.data?.customParams) {
|
|||
|
|
extraSaveData[this.props.data.customParams] = this.props.data.ID
|
|||
|
|
}
|
|||
|
|
const id = btnConfig.btnType !== 10 && record ? (btnConfig.btnType === -1 ? record.parent_id : record.id) : ''
|
|||
|
|
const copySrcId = btnConfig.btnType === 10 && record ? record.id : ''
|
|||
|
|
return (
|
|||
|
|
<EditModal
|
|||
|
|
key={record ? (record.id + btnConfig.id) : btnConfig.id}
|
|||
|
|
formCode={this.props.formCode}
|
|||
|
|
id={id}
|
|||
|
|
copySrcId={copySrcId}
|
|||
|
|
data={data}
|
|||
|
|
extraSaveData={extraSaveData}
|
|||
|
|
title={btnConfig.label}
|
|||
|
|
formParam={formParam}
|
|||
|
|
parentId={btnConfig.btnType === -1 ? record.parent_id : record.id}
|
|||
|
|
isAddH={btnConfig.btnType === 3 || btnConfig.btnType === -1}
|
|||
|
|
onSave={saveData => {
|
|||
|
|
this.updateTreeDataBySave(saveData)
|
|||
|
|
}}
|
|||
|
|
click={this.click}>
|
|||
|
|
<Icon type={btnConfig.icon} title={btnConfig.label} />
|
|||
|
|
</EditModal>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
// 节点删除
|
|||
|
|
else if (btnConfig.btnType === 4) {
|
|||
|
|
return (
|
|||
|
|
<Popconfirm
|
|||
|
|
title="是否确定删除?"
|
|||
|
|
onConfirm={this.deleteTreeNode.bind(this, params)}
|
|||
|
|
onVisibleChange={visible => this.setState({ showModal: visible })}
|
|||
|
|
icon={<Icon type="exclamation-circle" style={{ color: '#faad14' }} />}
|
|||
|
|
>
|
|||
|
|
<Icon type={btnConfig.icon} title={btnConfig.label} />
|
|||
|
|
</Popconfirm>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
// 列表查看
|
|||
|
|
else if (btnConfig.btnType === 12) {
|
|||
|
|
return (
|
|||
|
|
<TableModal
|
|||
|
|
key={record ? (record.id + btnConfig.id) : btnConfig.id}
|
|||
|
|
formCode={btnConfig.formCode}
|
|||
|
|
id={record.id}
|
|||
|
|
customParams={btnConfig.customParams}
|
|||
|
|
formParam={formParam}
|
|||
|
|
data={record}
|
|||
|
|
title={btnConfig.label}
|
|||
|
|
parentId={btnConfig.btnType === -1 ? record.parent_id : record.id}
|
|||
|
|
click={this.click}>
|
|||
|
|
<Icon type={btnConfig.icon} title={btnConfig.label} />
|
|||
|
|
</TableModal>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
// 组合表单
|
|||
|
|
else if (btnConfig.btnType === 14) {
|
|||
|
|
return (
|
|||
|
|
<CombinationModal
|
|||
|
|
key={record ? (record.id + btnConfig.id) : btnConfig.id}
|
|||
|
|
formCode={btnConfig.formCode}
|
|||
|
|
id={record.id}
|
|||
|
|
customParams={btnConfig.customParams}
|
|||
|
|
formParam={formParam}
|
|||
|
|
data={record}
|
|||
|
|
title={btnConfig.label}
|
|||
|
|
parentId={btnConfig.btnType === -1 ? record.parent_id : record.id}
|
|||
|
|
click={this.click}>
|
|||
|
|
<Icon type={btnConfig.icon} title={btnConfig.label} />
|
|||
|
|
</CombinationModal>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
// 自定义弹窗
|
|||
|
|
else if (btnConfig.btnType === 0) {
|
|||
|
|
return (
|
|||
|
|
<FormModal
|
|||
|
|
key={record ? (record.id + btnConfig.id) : btnConfig.id}
|
|||
|
|
formCode={btnConfig.formCode}
|
|||
|
|
id={record.id}
|
|||
|
|
customParams={btnConfig.customParams}
|
|||
|
|
formParam={formParam}
|
|||
|
|
data={record}
|
|||
|
|
title={btnConfig.label}
|
|||
|
|
parentId={btnConfig.btnType === -1 ? record.parent_id : record.id}
|
|||
|
|
click={this.click}>
|
|||
|
|
<Icon type={btnConfig.icon} title={btnConfig.label} />
|
|||
|
|
</FormModal>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
// 无树数据时,新增顶级节点
|
|||
|
|
else {
|
|||
|
|
const data = {}
|
|||
|
|
if (this.props.data?.Filter) {
|
|||
|
|
data.record = {
|
|||
|
|
[this.props.data.Filter]: this.props.data.ID
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
const extraSaveData = {}
|
|||
|
|
if (this.props.data?.customParams) {
|
|||
|
|
extraSaveData[this.props.data.customParams] = this.props.data.ID
|
|||
|
|
}
|
|||
|
|
return (
|
|||
|
|
<EditModal
|
|||
|
|
formCode={this.props.formCode}
|
|||
|
|
title='新增'
|
|||
|
|
isAddH={true}
|
|||
|
|
data={data}
|
|||
|
|
onSave={saveData => {
|
|||
|
|
this.updateTreeDataBySave(saveData)
|
|||
|
|
}}
|
|||
|
|
extraSaveData={extraSaveData}
|
|||
|
|
click={this.click}>
|
|||
|
|
{
|
|||
|
|
btnConfig.btnType === -1
|
|||
|
|
? <Icon type={btnConfig.icon} title={btnConfig.label} />
|
|||
|
|
: <Button type="primary" icon="plus">添加</Button>
|
|||
|
|
}
|
|||
|
|
</EditModal>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
deleteTreeNode = (params) => {
|
|||
|
|
const { treeCode = this.defaultTreeCode, record } = params
|
|||
|
|
const treeConfig = this.getTreeConfig({ treeCode })
|
|||
|
|
if (treeConfig) {
|
|||
|
|
const { deleteApi } = treeConfig
|
|||
|
|
if (deleteApi) {
|
|||
|
|
this.props.dispatch({
|
|||
|
|
type: 'app/deleteItemBatch',
|
|||
|
|
payload: {
|
|||
|
|
ids: record.id
|
|||
|
|
},
|
|||
|
|
url: deleteApi,
|
|||
|
|
onComplete: (ret) => {
|
|||
|
|
if (ret) {
|
|||
|
|
message.success('删除成功')
|
|||
|
|
this.updateTreeDataBySave()
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
updateTreeDataBySave = () => {
|
|||
|
|
this.onLoadTreeData({ treeCode: this.defaultTreeCode })
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/*
|
|||
|
|
根据树编号渲染树
|
|||
|
|
*/
|
|||
|
|
getRenderTreeByConfig (treeCode) {
|
|||
|
|
if (treeCode === undefined) {
|
|||
|
|
treeCode = this.defaultTreeCode
|
|||
|
|
}
|
|||
|
|
const treeConfig = this.getTreeConfig({ treeCode })
|
|||
|
|
if (treeConfig) {
|
|||
|
|
const treeData = this.getTreeData({ treeCode })
|
|||
|
|
const { formCode, queryCode } = treeConfig
|
|||
|
|
if (treeConfig.showModel == 1) {
|
|||
|
|
return (
|
|||
|
|
<>
|
|||
|
|
<Search
|
|||
|
|
formCode={formCode}
|
|||
|
|
formParam={this.props.formParam}
|
|||
|
|
code={queryCode}
|
|||
|
|
onSearch={(value) => this.onLoadTreeData({ treeCode, searchValue: value })}
|
|||
|
|
/>
|
|||
|
|
{
|
|||
|
|
treeData && treeData.length
|
|||
|
|
? (
|
|||
|
|
<VPage
|
|||
|
|
treeData={treeData}
|
|||
|
|
treeConfig={treeConfig}
|
|||
|
|
formParam={formParam}
|
|||
|
|
treePicFilter={this.state.picFilter}
|
|||
|
|
getRenderBtn={this.getRenderBtn}
|
|||
|
|
onSave={this.updateTreeDataBySave}
|
|||
|
|
/>
|
|||
|
|
)
|
|||
|
|
: null
|
|||
|
|
}
|
|||
|
|
{
|
|||
|
|
treeData && treeData.length === 0 && treeConfig.canAddNode
|
|||
|
|
? <div className={styles.treeVBox}>{this.getRenderBtn()}</div>
|
|||
|
|
: (
|
|||
|
|
treeData && treeData.length === 0
|
|||
|
|
? <div className={styles.treeVBox}><Empty style={{ position: 'relative', top: '50%', transform: 'translateY(-50%)' }} /></div>
|
|||
|
|
: (!treeData ? <div className={styles.treeVBox}><DataLoading /></div> : null)
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
</>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
return (
|
|||
|
|
<>
|
|||
|
|
<Search
|
|||
|
|
formCode={formCode}
|
|||
|
|
formParam={this.props.formParam}
|
|||
|
|
code={queryCode}
|
|||
|
|
onSearch={(value) => this.onLoadTreeData({ treeCode, searchValue: value })}
|
|||
|
|
/>
|
|||
|
|
<div className={styles.treeHBox}>
|
|||
|
|
{
|
|||
|
|
(treeData || []).map(item => {
|
|||
|
|
return (
|
|||
|
|
<OrganizationTree
|
|||
|
|
key={`${item.node.id}--rootTree`}
|
|||
|
|
data={item}
|
|||
|
|
node={{
|
|||
|
|
id: 'node.id',
|
|||
|
|
label: 'node.name',
|
|||
|
|
expand: 'expand',
|
|||
|
|
children: 'children'
|
|||
|
|
}}
|
|||
|
|
expandLevel={treeConfig.expandLevel}
|
|||
|
|
renderContent={this.MyNode}
|
|||
|
|
/>
|
|||
|
|
)
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
{
|
|||
|
|
treeData && treeData.length === 0 && treeConfig.canAddNode
|
|||
|
|
? this.getRenderBtn()
|
|||
|
|
: (
|
|||
|
|
treeData && treeData.length === 0
|
|||
|
|
? <Empty style={{ position: 'relative', top: '50%', transform: 'translateY(-50%)' }} />
|
|||
|
|
: (!treeData ? <DataLoading /> : null)
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
</div>
|
|||
|
|
</>
|
|||
|
|
)
|
|||
|
|
}
|
|||
|
|
return <div />
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export default TreeBaseComponent
|