123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821 |
- /*
- * @Author: code4eat awesomedema@gmail.com
- * @Date: 2022-12-16 09:42:52
- * @LastEditors: code4eat awesomedema@gmail.com
- * @LastEditTime: 2023-05-10 15:12:52
- * @FilePath: /BudgetManaSystem/src/pages/budgetMana/monthlySet/index.tsx
- * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
- */
- import { useEffect, useImperativeHandle, useRef, useState } from 'react';
- import './style.less';
- import { TreeProps, Input, Transfer, Popconfirm, Modal, TransferProps, Table } from 'antd';
- import { DataNode } from 'antd/es/tree';
- import expandedIcon from '../../../../../public/images/treenode_open.png';
- import closeIcon from '../../../../../public/images/treenode_collapse.png';
- import type { ColumnsType, TableRowSelection } from 'antd/es/table/interface';
- import { createFromIconfontCN } from '@ant-design/icons';
- import { addData, delData, editData, getMenuContentType, getMenuRelaActDic, getTableDataRequest, getTreeData, getTreeDataRespType, updateFuncDic } from './service';
- import { TransferDirection, TransferItem } from 'antd/es/transfer';
- import difference from 'lodash/difference';
- import 'dayjs/locale/zh-cn';
- import locale from 'antd/es/date-picker/locale/zh_CN';
- import React from 'react';
- import DirectoryTree from 'antd/es/tree/DirectoryTree';
- import { ActionType, ProColumns } from '@ant-design/pro-table';
- import KCTable from '@/components/kcTable';
- import { getDeepestTreeData } from '@/utils';
- import ProForm, { ModalForm, ProFormDependency, ProFormDigit, ProFormInstance, ProFormItem, ProFormRadio, ProFormSelect, ProFormText, ProFormTextArea } from '@ant-design/pro-form';
- import { KCInput } from '@/components/KCInput';
- import { UserRelaSeletDataListType } from '@/service/user';
- const IconFont = createFromIconfontCN({
- scriptUrl: '//at.alicdn.com/t/c/font_1927152_4nm5kxbv4m3.js',
- });
- const SearchIcon = createFromIconfontCN({
- scriptUrl: '//at.alicdn.com/t/c/font_1927152_g1njmm1kh7b.js',
- });
- export type TableListItem = {
- key: number;
- name: string;
- };
- const MonthlyInfoCheck: React.FC = () => {
- const [treeData, set_treeData] = useState<getTreeDataRespType[]>([]);
- const [currentSelectedTreeNode, set_currentSelectedTreeNode] = useState<any | undefined>();
- const [reload, set_reload] = useState(false);
- const [tableDataFilterParams, set_tableDataFilterParams] = useState<any | undefined>();
- const [expandedKeys, setExpandedKeys] = useState<React.Key[]>([]);
- const [searchValue, setSearchValue] = useState('');
- const [autoExpandParent, setAutoExpandParent] = useState(true);
- const [tableDataSearchKeywords, set_tableDataSearchKeywords] = useState<string>('');
- const [currentOperateRow, set_currentOperateRow] = useState<any | undefined>(undefined); //当前操作的表格行数据
-
- const [contentType, set_contentType] = useState<any[]>([]); //菜单内容类型列表
- const tableRef = useRef<ActionType>();
- const formRef = useRef<ProFormInstance>();
-
- const transferTableColumn = [
- {
- title: '功能名称',
- dataIndex: 'name',
- key: 'name',
- },
- {
- title: '功能代码',
- dataIndex: 'code',
- key: 'code',
- },
- ];
- const columns = [
- {
- title: '名称',
- dataIndex: 'name',
- key: 'name',
- },
- {
- title: '类型',
- dataIndex: 'contentType',
- key: 'contentType',
- render: (_: any, record: any) => {
- //console.log({ record });
- switch (record.type) {
- case 0:
- return '目录'
- case 1:
- return '菜单'
- case 2:
- return 'api'
- case 3:
- return '系统'
- case 4:
- return '有数bi'
- case 5:
- return '体系'
- case 6:
- return '中心层'
- case 7:
- return '平台层'
- default:
- break;
- }
- },
- },
- {
- title: 'Path',
- dataIndex: 'path',
- key: 'path',
- },
- {
- title: '内容',
- dataIndex: 'contentType',
- key: 'contentType',
- valueEnum: {
- 0: '一般',
- 1: '报告',
- 2: '大屏',
- 3: '填报',
- 4: '空白',
- 5: '静态'
- }
- },
- {
- title: '功能',
- dataIndex: 'deptName',
- key: 'deptName',
- render: (_: any, record: any) => {
- if (record.functionList) {
- return record.functionList.reduce((prev: any, cur: any) => {
- return `${prev ? prev + ' | ' : prev}${cur.name}`
- }, '')
- }
- return '-'
- }
- },
- {
- title: '操作',
- key: 'option',
- width: 120,
- fixed: 'right',
- valueType: 'option',
- render: (_: any, record: any) => {
- return record.type != 1 && record.type != 2 && record.type != 4 ? [
- <UpDataActBtn key={'add'} record={record} type='ADD' />,
- <UpDataActBtn key={'act'} record={record} type='EDIT' />,
- <Popconfirm
- title="是否确认删除?"
- key="del"
- onConfirm={() => delMenuHandle(record)}
- >
- <a>删除</a>
- </Popconfirm>
- ] : [
- <a key={'fuc'} onClick={() => addFuncHandle(record)}>功能</a>,
- <UpDataActBtn key={'act'} record={record} type='EDIT' />,
- <Popconfirm
- title="是否确认删除?"
- key="del"
- onConfirm={() => delMenuHandle(record)}
- >
- <a>删除</a>
- </Popconfirm>
- ]
- },
- },
- ]
- const onSelect: TreeProps['onSelect'] = (selectedKeys, info) => {
- //console.log('selected', selectedKeys, info);
- const { node } = info;
- set_currentSelectedTreeNode(node);
- };
- const getContentType = async () => {
- const resp = await getMenuContentType();
- if (resp) {
- set_contentType(resp.list);
- }
- }
- const getTableData = async (params: any, sort: any, filter: any) => {
- set_reload(false);
- if (currentSelectedTreeNode) {
- const resp = await getTableDataRequest(params);
- if (resp) {
- return {
- data: resp,
- success: true,
- }
- }
- return {
- data: [],
- success: true
- }
- }
- return []
- }
- const addFuncHandle = (record: any) => {
- set_currentOperateRow(record);
- const ref = React.createRef<{ save: any; }>();
- Modal.confirm({
- title: '菜单功能设置(核算单元管理)',
- icon: '',
- width: 672,
- content: <TableTransfer
- ref={ref}
- record={record}
- leftColumns={transferTableColumn}
- rightColumns={transferTableColumn} dataSource={[]}
- ></TableTransfer>,
- onOk: () => {
- return ref.current && ref.current.save();
- }
- })
- }
- const delMenuHandle = async (record: any) => {
- const resp = await delData(record.menuId);
- resp && set_reload(true);
- }
- interface DataType {
- key: string;
- title: string;
- description: string;
- disabled: boolean;
- tag: string;
- }
- interface TableTransferProps extends TransferProps<TransferItem> {
- dataSource: DataType[];
- leftColumns: ColumnsType<DataType>;
- rightColumns: ColumnsType<DataType>;
- record: any
- }
- const TableTransfer = React.forwardRef(({ leftColumns, rightColumns, record, ...restProps }: TableTransferProps, ref) => {
- const [_data, _set_data] = useState<any>();
- const [targetKeys, setTargetKeys] = useState<string[]>([]);
- const [datasource, set_datasource] = useState<any[]>([]);
- const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
- //获取页面权限字典
- const getFuncList = async () => {
- const resp = await getMenuRelaActDic();
- if (resp) {
- set_datasource(resp);
- if (record && record.functionList) {
- const defaultSelctedkeys = record.functionList.map((item: any) => item.code);
- setTargetKeys(defaultSelctedkeys);
- }
- }
- }
- const onChange = (nextTargetKeys: string[]) => {
- setTargetKeys(nextTargetKeys);
- };
- const onSelectChange = (sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
- //console.log('sourceSelectedKeys:', sourceSelectedKeys,'targetSelectedKeys:',targetSelectedKeys);
- setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys]);
- };
- useImperativeHandle(ref, () => ({
- save: async () => {
- const data = datasource.filter(item => targetKeys.includes(item.code));
- const resp = await updateFuncDic({
- menuId: record.menuId,
- function: data
- });
- if (resp) {
- set_reload(true);
- }
- }
- }));
- useEffect(() => {
- getFuncList();
- }, [])
- return (
- <Transfer className='TableTransfer' showSearch
- titles={['待选项目', '已选项目']}
- locale={{
- itemUnit: '项',
- itemsUnit: '项',
- searchPlaceholder: '请输入'
- }}
- onChange={onChange}
- onSelectChange={onSelectChange}
- dataSource={datasource}
- rowKey={record => record.code}
- targetKeys={targetKeys}
- selectedKeys={selectedKeys}
- filterOption={(inputValue, item) => {
- return item.name!.indexOf(inputValue) !== -1
- }}
- >
- {({
- direction,
- filteredItems,
- onItemSelectAll,
- onItemSelect,
- selectedKeys: listSelectedKeys,
- disabled: listDisabled,
- }) => {
- // console.log({ filteredItems, listSelectedKeys,direction });
- const columns = direction === 'left' ? leftColumns : rightColumns;
- const rowSelection: TableRowSelection<TransferItem> = {
- getCheckboxProps: (item) => ({ disabled: listDisabled || item.disabled }),
- onSelectAll(selected, selectedRows) {
- const treeSelectedKeys = selectedRows.map(({ code }) => code);
- const diffKeys = selected
- ? difference(treeSelectedKeys, listSelectedKeys)
- : difference(listSelectedKeys, treeSelectedKeys);
- onItemSelectAll(diffKeys as string[], selected);
- },
- onSelect({ code }, selected) {
- onItemSelect(code as string, selected);
- },
- selectedRowKeys: listSelectedKeys,
- };
- return (
- <Table
- rowSelection={rowSelection}
- columns={columns as TransferItem[]}
- dataSource={filteredItems}
- size="small"
- rowKey={'code'}
- style={{ pointerEvents: listDisabled ? 'none' : undefined }}
- onRow={({ code, disabled: itemDisabled }) => ({
- onClick: () => {
- if (itemDisabled || listDisabled) return;
- onItemSelect(code as string, !listSelectedKeys.includes(code as string));
- },
- })}
- />
- );
- }}
- </Transfer>
- )
- })
- const dataList: any[] = [];
- const getParentKey = (key: React.Key, tree: any[]): React.Key => {
- let parentKey: React.Key;
- for (let i = 0; i < tree.length; i++) {
- const node = tree[i];
- if (node.children) {
- if (node.children.some((item: { code: React.Key; }) => item.code === key)) {
- parentKey = node.code;
- } else if (getParentKey(key, node.children)) {
- parentKey = getParentKey(key, node.children);
- }
- }
- }
- return parentKey!;
- };
- const onTreeSearchKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
- const { value } = e.target;
- const newExpandedKeys = dataList
- .map((item) => {
- if (item.name.indexOf(value) > -1) {
- return getParentKey(item.code, treeData);
- }
- return null;
- });
- const b = newExpandedKeys.filter((item, i, self) => item && self.indexOf(item) === i);
- setExpandedKeys(newExpandedKeys as React.Key[]);
- setSearchValue(value);
- setAutoExpandParent(true);
- }
- const onExpand = (newExpandedKeys: React.Key[]) => {
- setExpandedKeys(newExpandedKeys);
- setAutoExpandParent(false);
- };
- const generateList = (data: getTreeDataRespType[]) => {
- for (let i = 0; i < data.length; i++) {
- const node = data[i];
- const { code, name } = node;
- dataList.push({ code, name: name });
- if (node.children) {
- generateList(node.children);
- }
- }
- };
- generateList(treeData as any);
- const getTreeReqFunc = async (name?: string) => {
- const resp = await getTreeData();
- set_treeData(resp);
- }
- const tableDataSearchHandle = (paramName: string) => {
- set_tableDataFilterParams({
- ...tableDataFilterParams,
- [`${paramName}`]: tableDataSearchKeywords
- })
- }
- const updateTable = async (type: 'EDIT' | "ADD", formVal: any, record: any) => {
- if (type == 'ADD') {
- let data = undefined;
- if (record) {
- //添加操作
- data = { ...formVal, parentId: record.menuId, systemId: record.systemId }
- } else {
- //新增
- data = { ...formVal, parentId: currentSelectedTreeNode.code, systemId: currentSelectedTreeNode.code }
- }
- const resp = await addData({ ...data });
- if (resp) {
- set_reload(true);
- }
- }
- if (type == 'EDIT') {
- const resp = await editData({ ...record, ...formVal });
- if (resp) {
- set_reload(true);
- }
- }
- set_currentOperateRow(undefined);
- return true
- }
- const UpDataActBtn = ({ record, type }: { record: any, type: 'EDIT' | 'ADD' }) => {
- return (
- <ModalForm
- className='systemNavManaForm'
- title={`${type == 'EDIT' ? '编辑' : '新增'}菜单`}
- width={688}
- initialValues={type == 'EDIT' ? { ...record } : { isHomepage: 0 }}
- trigger={
- type == 'EDIT' ? <a key="edit" >编辑</a> : record ? <a className='add'>添加</a> : <span>新增</span>
- }
- formRef={formRef}
- grid={true}
- onFinish={(val) => {
- set_currentOperateRow(record);
- return updateTable(type, val, record)
- }}
- >
- <ProFormText
- name="name"
- label="名称:"
- placeholder="请输入"
- colProps={{ span: 12 }}
- rules={[{ required: true, message: '名称不能为空!' }]}
- />
- <ProFormSelect
- name="type"
- label="类型:"
- placeholder="请输入"
- colProps={{ span: 12 }}
- options={[
- {
- label: '目录',
- value: 0
- },
- {
- label: '菜单',
- value: 1
- }
- ]}
- rules={[{ required: true, message: '类型不能为空!' }]}
- />
- <ProFormText
- name="path"
- label="Path:"
- placeholder="请输入"
- colProps={{ span: 12 }}
- rules={[{ required: true, message: 'Path不能为空!' }]}
- />
- <ProFormText
- name="icon"
- label="icon:"
- placeholder="请输入"
- colProps={{ span: 12 }}
- //rules={[{ required: true, message: '类型代码不能为空!' }]}
- />
- <ProFormDigit
- name="orderNum"
- label="顺序号:"
- width={'xs'}
- placeholder="请输入"
- colProps={{ span: 12 }}
- //rules={[{ required: true, message: '类型代码不能为空!' }]}
- />
- <ProFormDependency name={['type']}>
- {
- ({ type }) => type == 1 && (
- <ProFormRadio.Group
- name="isHomepage"
- label="是否首页:"
- width={'xs'}
- placeholder="请选择"
- colProps={{ span: 12 }}
- rules={[{ required: true, message: '是否为首页不能为空!' }]}
- options={[
- {
- label: '是',
- value: 1,
- },
- {
- label: '否',
- value: 0,
- },
- ]}
- //rules={[{ required: true, message: '类型代码不能为空!' }]}
- />
- )
- }
- </ProFormDependency>
- <ProFormDependency name={['type']}>
- {
- ({ type }) => type == 1 && (
- <ProForm.Group colProps={{ span: 12 }} align='start'>
- <ProFormSelect
- name="contentType"
- label="内容类型:"
- placeholder="请输入"
- width={100}
- colProps={{ span: 8 }}
- request={async () => {
- if(contentType){
- return contentType.map((a:any)=>({label:a.name,value:Number(a.code)}))
- }
- return []
- }}
- fieldProps={{
- onChange(value, option) {
- if (value == 1) {
- //报告页面
- const need = contentType.filter((item:any)=>item.code == `${value}`);
- if(need.length>0)
- formRef.current?.setFieldValue('url',need[0].value);
- }
- },
- }}
- // options={[
- // { label: '一般', value: 0 },
- // { label: '报告', value: 1 },
- // { label: '大屏', value: 2 },
- // { label: '填报', value: 3 },
- // { label: '空白', value: 4 },
- // { label: '静态', value: 5 },
- // ]}
- rules={[{ required: true, message: '类型不能为空!' }]}
- />
- <ProFormDependency name={['contentType']}>
- {
- ({ contentType }) => {
- return contentType == 1 && (
- <div style={{ position: 'relative', top: 24 }}>
- <ProFormText
- noStyle
- width={210}
- className='reportId'
- name="reportId"
- placeholder="请输入报告Id"
- colProps={{ span: 16 }}
- //rules={[{ required: true, message: '类型代码不能为空!' }]}
- />
- </div>
- )
- }
- }
- </ProFormDependency>
- </ProForm.Group>
- )
- }
- </ProFormDependency>
- <ProFormDependency name={['type']}>
- {
- ({ type }) => type == 1 && (
- <ProFormText
- name="url"
- label="URL:"
- placeholder="请输入"
- colProps={{ span: 12 }}
- //rules={[{ required: true, message: '类型代码不能为空!' }]}
- />
- )
- }
- </ProFormDependency>
- <ProFormTextArea
- name="description"
- label="描述:"
- placeholder="请输入"
- colProps={{ span: 24 }}
- />
- </ModalForm>
- )
- }
- useEffect(() => {
- if (currentSelectedTreeNode) {
- set_tableDataFilterParams({ ...tableDataFilterParams, systemId: currentSelectedTreeNode.code })
- }
- }, [currentSelectedTreeNode]);
- useEffect(() => {
- //初始化左侧树结构数据后
- if (treeData?.length > 0) {
- if (treeData[0].children && treeData[0].children.length > 0) {
- const [node, nodeParent] = getDeepestTreeData(treeData[0], 'children');
- set_currentSelectedTreeNode(node);
- setExpandedKeys([nodeParent.code]);
- }
- }
- }, [treeData]);
- useEffect(() => {
- getTreeReqFunc();
- getContentType();
- }, []);
- return (
- <div className='SystemNavMana'>
- <div className='leftTree'>
- <div className='search'>
- <Input
- className='searchInput'
- placeholder="请输入"
- size='small'
- allowClear
- style={{ marginBottom: 16 }}
- onChange={onTreeSearchKeyChange}
- suffix={
- <SearchIcon type='iconsousuo' />
- }
- />
- </div>
- {
- treeData && treeData.length > 0 && (
- <DirectoryTree
- fieldNames={{ title: 'name', key: 'code' }}
- rootStyle={{ height: '100%', paddingBottom: 50, overflowY: 'scroll', overflowX: 'hidden' }}
- onSelect={onSelect}
- onExpand={onExpand}
- expandedKeys={expandedKeys}
- autoExpandParent={autoExpandParent}
- selectedKeys={currentSelectedTreeNode ? [currentSelectedTreeNode.code] : []}
- blockNode={true}
- icon={() => null}
- titleRender={
- (nodeData: any) => {
- const strTitle = nodeData.name as string;
- const index = strTitle.indexOf(searchValue);
- const beforeStr = strTitle.substring(0, index);
- const afterStr = strTitle.slice(index + searchValue.length);
- const title =
- index > -1 ? (
- <span>
- {beforeStr}
- <span className="site-tree-search-value" style={{ color: 'red', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{searchValue}</span>
- {afterStr}
- </span>
- ) : (
- <span className='strTitle'>{strTitle}</span>
- );
- return <div style={{
- display: 'flex', flexDirection: 'row',
- width: '100%',
- justifyContent: 'flex-start', alignItems: 'center', height: 32,
- borderRadius: '4px',
- overflow: 'hidden',
- color: '#17181A',
- textOverflow: 'ellipsis',
- whiteSpace: 'nowrap'
- }}>{title}</div>
- }
- }
- defaultSelectedKeys={[treeData[0].children[0].code]}
- treeData={treeData as unknown as DataNode[]}
- // treeData={treeDataNew}
- switcherIcon={(props: any) => {
- const { expanded } = props;
- //return <button className='site-table-row-expand-icon site-table-row-expand-icon-expanded'></button>
- return !expanded ? <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={expandedIcon} /> : <img style={{ width: 20, height: 20, position: 'relative', top: 5 }} src={closeIcon} />
- }}
- />
- )
- }
- </div>
- {/* <div style={{width:16,height:'92vh',background:'#F5F7FA'}}></div> */}
- <div className='rightContent'>
- <div className='tableToolbar'>
- <div className='filter'>
- <div className='filterItem'>
- <span className='label'>检索:</span>
- <KCInput placeholder={'请输入菜单名称'} style={{ width: 160 }} search allowClear
- onChange={(e) => {
- set_tableDataSearchKeywords(e.target.value);
- if (e.target.value.length == 0) {
- set_tableDataFilterParams({
- ...tableDataFilterParams,
- name: ''
- });
- }
- }}
- onSearch={() => tableDataSearchHandle('name')}
- />
- </div>
- </div>
- <div className={'btnGroup'}>
- <UpDataActBtn key={'act'} record={undefined} type='ADD' />
- </div>
- </div>
- {currentSelectedTreeNode && <KCTable pagination={false} reload={reload} newVer params={tableDataFilterParams} rowKey='menuId' columns={columns as ProColumns[]} request={(params: any, sort: any, filter: any) => getTableData(params, sort, filter)} />}
- </div>
- </div>
- );
- };
- export default MonthlyInfoCheck;
|