diff --git a/config/defaultSettings.ts b/config/defaultSettings.ts index 1077b94..b0e5b74 100644 --- a/config/defaultSettings.ts +++ b/config/defaultSettings.ts @@ -12,7 +12,7 @@ const Settings: LayoutSettings & { fixedHeader: false, fixSiderbar: true, colorWeak: false, - title: 'Pro', + title: 'TBG', pwa: false, logo: '/pro_icon.svg', iconfontUrl: '', diff --git a/config/proxy.ts b/config/proxy.ts index 03d511e..e313afd 100644 --- a/config/proxy.ts +++ b/config/proxy.ts @@ -11,7 +11,8 @@ export default { // localhost:8000/api/** -> https://preview.pro.ant.design/api/** '/tbg/api/v1': { // 要代理的地址 - target: 'http://192.168.88.238:9999', + // target: 'http://81.71.13.173:9080', + target: 'http://127.0.0.1:9999', // 配置了这个可以从 http 代理到 https // 依赖 origin 的功能可能需要这个,比如 cookie changeOrigin: true, diff --git a/src/access.ts b/src/access.ts index 774d6c6..1037848 100644 --- a/src/access.ts +++ b/src/access.ts @@ -10,11 +10,11 @@ export default function access(initialState: { return { canAdmin: currentUser && currentUser.access === 'admin', normalRouteFilter: (route: any) => { - return true; - // if (routeList == null || routeList == undefined || routeList.length == 0) { - // return true; - // } - // return routeList.includes(route.name); + // return true; + if (routeList == null || routeList == undefined || routeList.length == 0) { + return true; + } + return routeList.includes(route.name); }, }; } diff --git a/src/app.tsx b/src/app.tsx index 812ea93..f0d6e93 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -4,18 +4,21 @@ import { history } from 'umi'; import RightContent from '@/components/RightContent'; import RoutePath from '@/routes/routePath'; import { CACHE_TOKEN } from '@/constants/cacheKey'; -// import { getRoleList } from './services/system/role'; +import { getRoleList } from './services/system/role'; // ProLayout 支持的api https://procomponents.ant.design/components/layout -// export async function getInitialState() { -// if (localStorage.getItem(CACHE_TOKEN)) { -// const res = await getRoleList({}); -// return { -// routeList: res, -// }; -// } -// } +export async function getInitialState() { + if (localStorage.getItem(CACHE_TOKEN)) { + const res = await getRoleList({}); + // return { + // routeList: res, + // }; + return { + routeList: [], + }; + } +} export const layout: RunTimeLayoutConfig = ({ initialState }) => { return { diff --git a/src/components/Table/ConfirmButton/index.less b/src/components/Table/ConfirmButton/index.less index 61897f7..763d63d 100644 --- a/src/components/Table/ConfirmButton/index.less +++ b/src/components/Table/ConfirmButton/index.less @@ -1,9 +1,3 @@ -.delete-btn { - color: @error-color; - &:hover { - color: @error-color !important; - } -} .disabled { color: @disabled-color; cursor: not-allowed; @@ -11,3 +5,10 @@ color: @disabled-color !important; } } + +.confirm-btn { + color: @success-color; + &:hover { + color: @success-color !important; + } +} diff --git a/src/components/Table/ConfirmButton/index.tsx b/src/components/Table/ConfirmButton/index.tsx index f1b19ec..1ba6859 100644 --- a/src/components/Table/ConfirmButton/index.tsx +++ b/src/components/Table/ConfirmButton/index.tsx @@ -17,7 +17,7 @@ const ConfirmButton: React.FC = ({ }) => { return ( - {buttonName} + {buttonName} ); }; diff --git a/src/components/Table/RejectButton/index.less b/src/components/Table/RejectButton/index.less new file mode 100644 index 0000000..65c8599 --- /dev/null +++ b/src/components/Table/RejectButton/index.less @@ -0,0 +1,14 @@ +.disabled { + color: @disabled-color; + cursor: not-allowed; + &:hover { + color: @disabled-color !important; + } +} + +.reject-btn { + color: @error-color; + &:hover { + color: @error-color !important; + } +} diff --git a/src/components/Table/RejectButton/index.tsx b/src/components/Table/RejectButton/index.tsx new file mode 100644 index 0000000..7573339 --- /dev/null +++ b/src/components/Table/RejectButton/index.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { Popconfirm } from 'antd'; +import styles from './index.less'; +import classNames from 'classnames'; + +interface PropsType { + onConfirm: () => void; + title?: string; + buttonName?: string; + disabled?: boolean; +} +const ConfirmButton: React.FC = ({ + onConfirm, + disabled = false, + title = '', + buttonName = '', +}) => { + return ( + + {buttonName} + + ); +}; +export default ConfirmButton; diff --git a/src/pages/Login/index.tsx b/src/pages/Login/index.tsx index 5152408..fb3105e 100644 --- a/src/pages/Login/index.tsx +++ b/src/pages/Login/index.tsx @@ -13,6 +13,7 @@ const Login: React.FC = () => { const { initialState, refresh } = useModel('@@initialState'); const handleSubmit = async (values: API.LoginParams) => { // 登录 + const res: any = await login({ ...values }); localStorage.setItem(CACHE_TOKEN, res.token); /** 此方法会跳转到 redirect 参数所在的位置 */ diff --git a/src/pages/Nft/NftToken/List/components/AddNftModel.tsx b/src/pages/Nft/NftToken/List/components/AddNftModel.tsx index 6b3a054..444368d 100644 --- a/src/pages/Nft/NftToken/List/components/AddNftModel.tsx +++ b/src/pages/Nft/NftToken/List/components/AddNftModel.tsx @@ -1,13 +1,19 @@ -import React, { useRef } from 'react'; +import React, { useRef, useState } from 'react'; import { createForm } from '@formily/core'; import { createSchemaField } from '@formily/react'; import Modal, { ModalProps } from '@/components/Modal'; // import { fetchTableData } from '@/utils/table'; import { Form, FormItem, Input, NumberPicker } from '@formily/antd'; +import { Button } from 'antd'; +import { initWeb3, NFTMint } from '@/utils/web3'; +import { getContractInfo } from '@/services/contract'; +import { getNFTContractList, mintNFT } from '@/services/nft'; +import { ContractType } from '@/constants/enum/contract'; interface AddNftModalPropsType extends ModalProps { - onOk: (val: any) => void; + onOk: () => void; onCancel: () => void; + // loading: boolean; } const SchemaField = createSchemaField({ @@ -21,10 +27,26 @@ const SchemaField = createSchemaField({ const form = createForm({}); const AddNftModal = ({ onOk, onCancel, ...rest }: AddNftModalPropsType) => { - const handleOk = () => { - form.submit(() => { + const [loading, setLoading] = useState(false); + + const handleOk = async () => { + form.submit(async () => { + setLoading(true); const formState = form.getFormState(); - onOk(formState.values); + await initWeb3(); + const contractInfo = await getContractInfo({ erc: ContractType.NFT721 }); + const res = await getNFTContractList(); + const tx_hash = await NFTMint({ + abi: contractInfo.abi, + address: res.items[0].address, + toAddress: formState.values.toAddress, + name: formState.values.name, + }); + console.log('tx_hash = ', tx_hash); + formState.values.tx_hash = tx_hash; + await mintNFT(formState.values); + setLoading(false); + onOk(); }); }; const handleCancel = () => { @@ -32,15 +54,21 @@ const AddNftModal = ({ onOk, onCancel, ...rest }: AddNftModalPropsType) => { }; return ( - + + 取消 + , + , + ]} + {...rest} + >
- { const tableRef = useRef(); const [visible, setVisible] = useState(false); const columns: ProColumns[] = [ - { - title: 'TokenId', - dataIndex: 'token_id', - width: '10%', - hideInSearch: true, - }, { title: '所有者地址', dataIndex: 'address', @@ -74,19 +65,7 @@ const Address: React.FC = () => { onCancel={function () { setVisible(false); }} - onOk={async function (val: any): Promise { - await checkTokenId({ token_id: val.token_id }); - await initWeb3(); - const contractInfo = await getContractInfo({ erc: ContractType.NFT721 }); - const res = await getNFTContractList(); - await NFTMint({ - abi: contractInfo.abi, - address: res.items[0].address, - toAddress: val.toAddress, - name: val.name, - token_id: val.token_id, - }); - await mintNFT(val); + onOk={async function (): Promise { tableRef.current?.reload(); setVisible(false); }} diff --git a/src/pages/Recharge/CoinType/components/EditCoinTypeModal.tsx b/src/pages/Recharge/CoinType/components/EditCoinTypeModal.tsx index 9ccabea..27e1010 100644 --- a/src/pages/Recharge/CoinType/components/EditCoinTypeModal.tsx +++ b/src/pages/Recharge/CoinType/components/EditCoinTypeModal.tsx @@ -3,7 +3,7 @@ import React, { useRef, useEffect } from 'react'; import { createForm } from '@formily/core'; import { createSchemaField } from '@formily/react'; import Modal, { ModalProps } from '@/components/Modal'; -import { Form, FormItem, Input, Select } from '@formily/antd'; +import { Form, FormItem, Input, NumberPicker } from '@formily/antd'; interface EditCoinTypeModalPropsType extends ModalProps { editModalData: any; @@ -15,7 +15,7 @@ const SchemaField = createSchemaField({ components: { FormItem, Input, - Select, + NumberPicker, }, }); diff --git a/src/pages/Recharge/Record/List/index.tsx b/src/pages/Recharge/Record/List/index.tsx index a0210e2..0d73bd3 100644 --- a/src/pages/Recharge/Record/List/index.tsx +++ b/src/pages/Recharge/Record/List/index.tsx @@ -10,7 +10,7 @@ const RecordList = () => { const columns: ProColumns[] = [ { title: '时间', - dataIndex: 'time', + dataIndex: 'searchTime', hideInTable: true, valueType: 'dateRange', ellipsis: true, @@ -55,12 +55,11 @@ const RecordList = () => { return ( { - if ((params.time ?? '') !== '') { - const start = Date.parse(params.time[0] + ' 00:00:00'); - const end = Date.parse(params.time[1] + ' 23:59:59'); + if ((params.searchTime ?? '') !== '') { + const start = Date.parse(params.searchTime[0] + ' 00:00:00'); + const end = Date.parse(params.searchTime[1] + ' 23:59:59'); params.start_time = start / 1000; params.end_time = end / 1000; } diff --git a/src/pages/Recharge/Wallet/components/AddWalletModal.tsx b/src/pages/Recharge/Wallet/components/AddWalletModal.tsx index 76d06c0..0541907 100644 --- a/src/pages/Recharge/Wallet/components/AddWalletModal.tsx +++ b/src/pages/Recharge/Wallet/components/AddWalletModal.tsx @@ -1,5 +1,5 @@ // 创建弹窗 -import React, { useRef } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { createForm, onFieldReact, FormPathPattern, Field } from '@formily/core'; import { FormProvider, createSchemaField } from '@formily/react'; import { getCoinTypeList } from '@/services/recharge/coinType'; @@ -20,39 +20,50 @@ const SchemaField = createSchemaField({ }, }); -const useAsyncDataSource = ( - pattern: FormPathPattern, - service: (field: Field) => Promise<{ label: string; value: any }[]>, -) => { - onFieldReact(pattern, (field) => { - service(field).then( - action.bound((data) => { - field.dataSource = data; - }), - ); - }); -}; - -const form = createForm({ - effects: () => { - // eslint-disable-next-line react-hooks/rules-of-hooks - useAsyncDataSource('name', async (field) => { - const list = await getCoinTypeList({ page: 1, size: 10 }); - const option = []; - for (let index = 0; index < list.items.length; index++) { - const element = list.items[index]; - const item = { - label: element.name, - value: element.name, - }; - option.push(item); - } - return option; - }); - }, -}); - const AddWalletModal = ({ onOk, onCancel, ...rest }: AddWalletModalPropsType) => { + const [coinTypeData, setCoinTypeData] = useState({}); + + const getSelectData = async () => { + const list = await getCoinTypeList({ page: 1, size: 10 }); + setCoinTypeData(list); + }; + + const useAsyncDataSource = ( + pattern: FormPathPattern, + service: (field: Field) => Promise<{ label: string; value: any }[]>, + ) => { + onFieldReact(pattern, (field) => { + service(field).then( + action.bound((data) => { + field.dataSource = data; + }), + ); + }); + }; + + const form = createForm({ + effects: () => { + // eslint-disable-next-line react-hooks/rules-of-hooks + useAsyncDataSource('name', async (field) => { + const list = coinTypeData; + const option = []; + for (let index = 0; index < list.items.length; index++) { + const element = list.items[index]; + const item = { + label: element.name, + value: element.name, + }; + option.push(item); + } + return option; + }); + }, + }); + + useEffect(() => { + getSelectData(); + }, []); + const handleOk = () => { form.submit(async () => { const formState = form.getFormState(); diff --git a/src/pages/Recharge/Wallet/components/EditWalletModal.tsx b/src/pages/Recharge/Wallet/components/EditWalletModal.tsx index 9477457..199916e 100644 --- a/src/pages/Recharge/Wallet/components/EditWalletModal.tsx +++ b/src/pages/Recharge/Wallet/components/EditWalletModal.tsx @@ -1,5 +1,5 @@ // 修改弹窗 -import React, { useRef, useEffect } from 'react'; +import React, { useRef, useEffect, useState } from 'react'; import { createForm, onFieldReact, FormPathPattern, Field } from '@formily/core'; import { getCoinTypeList } from '@/services/recharge/coinType'; import { FormProvider, createSchemaField } from '@formily/react'; @@ -22,6 +22,13 @@ const SchemaField = createSchemaField({ }); const EditWalletModal = ({ onOk, onCancel, editModalData, ...rest }: EditWalletModalPropsType) => { + const [coinTypeData, setCoinTypeData] = useState({}); + + const getSelectData = async () => { + const list = await getCoinTypeList({ page: 1, size: 10 }); + setCoinTypeData(list); + }; + const useAsyncDataSource = ( pattern: FormPathPattern, service: (field: Field) => Promise<{ label: string; value: any }[]>, @@ -39,7 +46,8 @@ const EditWalletModal = ({ onOk, onCancel, editModalData, ...rest }: EditWalletM effects: () => { // eslint-disable-next-line react-hooks/rules-of-hooks useAsyncDataSource('name', async (field) => { - const list = await getCoinTypeList({ page: 1, size: 10 }); + getSelectData(); + const list = coinTypeData; const option = []; for (let index = 0; index < list.items.length; index++) { const element = list.items[index]; diff --git a/src/pages/Recharge/Withdraw/List/index.tsx b/src/pages/Recharge/Withdraw/List/index.tsx index e76a2d2..4c1077f 100644 --- a/src/pages/Recharge/Withdraw/List/index.tsx +++ b/src/pages/Recharge/Withdraw/List/index.tsx @@ -5,10 +5,14 @@ import { fetchTableData } from '@/utils/table'; import ConfirmButton from '@/components/Table/ConfirmButton'; import moment from 'moment'; import { WithdrawType } from '@/constants/enum/withdraw'; +import RejectButton from '@/components/Table/RejectButton'; const WithdrawList = () => { - const handleConfirm = async (uuid) => { - await solveWithdraw({ uuid: uuid }); + const tableRef = useRef(); + + const handleClick = async (uuid, status) => { + await solveWithdraw({ uuid: uuid, status: status }); + tableRef.current?.reload(); }; const WithdrawTypeList = [ @@ -29,7 +33,6 @@ const WithdrawList = () => { }, ]; - const tableRef = useRef(); const columns: ProColumns[] = [ { title: '提现订单号', @@ -51,6 +54,7 @@ const WithdrawList = () => { { title: '类型', dataIndex: 'type', + hideInSearch: true, width: '10%', }, { @@ -76,14 +80,26 @@ const WithdrawList = () => { valueType: 'option', width: 150, render: (_, row) => [ - { - handleConfirm(row.uuid); - }} - />, + row.status === 30000 ? ( + { + handleClick(row.uuid, WithdrawType.SUCCESS); + }} + /> + ) : null, + row.status === 30000 ? ( + { + handleClick(row.uuid, WithdrawType.FAILED); + }} + /> + ) : null, ], }, ]; diff --git a/src/pages/System/Account/List/index.tsx b/src/pages/System/Account/List/index.tsx index 8776c1e..6cacf5d 100644 --- a/src/pages/System/Account/List/index.tsx +++ b/src/pages/System/Account/List/index.tsx @@ -8,7 +8,7 @@ import { } from '@/services/system/accountManage'; import { fetchTableData } from '@/utils/table'; import DeleteButton from '@/components/Table/DeleteButton'; -import { Switch } from 'antd'; +import { Popover, Switch } from 'antd'; import AddAccountModal from '../components/AddAccountModal'; import EditAccountModal from '../components/EditAccountModal'; @@ -52,14 +52,22 @@ const AccountManageList = () => { > 编辑 , - { - await changeUserStatus({ name: row.name, status: checked }); - }} - />, + +

账号启用/禁用

+ + } + > + { + await changeUserStatus({ name: row.name, status: checked }); + }} + /> +
, { diff --git a/src/pages/System/Account/components/AddAccountModal.tsx b/src/pages/System/Account/components/AddAccountModal.tsx index 290b927..c2a495b 100644 --- a/src/pages/System/Account/components/AddAccountModal.tsx +++ b/src/pages/System/Account/components/AddAccountModal.tsx @@ -1,11 +1,12 @@ // 创建弹窗 import React, { useEffect, useRef, useState } from 'react'; -import { createForm } from '@formily/core'; +import { createForm, FormPathPattern, onFieldReact } from '@formily/core'; import { createSchemaField } from '@formily/react'; import Modal, { ModalProps } from '@/components/Modal'; -import { Form, FormItem, Input, TreeSelect } from '@formily/antd'; +import { Form, FormItem, Input, Select } from '@formily/antd'; import { addUser } from '@/services/system/accountManage'; -import routes from '@/routes'; +import { action } from '@formily/reactive'; +import { getRoleList } from '@/services/system/role'; interface AddAccountModalPropsType extends ModalProps { onCancel: () => void; @@ -16,14 +17,53 @@ const SchemaField = createSchemaField({ components: { FormItem, Input, - TreeSelect, + Select, }, }); -const form = createForm({}); - const AddAccountModal = ({ onOk, onCancel, ...rest }: AddAccountModalPropsType) => { - const [treeData, setTreeData] = useState({}); + const [roleListData, setRoleListData] = useState({}); + + const useAsyncDataSource = ( + pattern: FormPathPattern, + service: (field: Field) => Promise<{ label: string; value: any }[]>, + ) => { + onFieldReact(pattern, (field) => { + service(field).then( + action.bound((data) => { + field.dataSource = data; + }), + ); + }); + }; + + const form = createForm({ + effects: () => { + // eslint-disable-next-line react-hooks/rules-of-hooks + useAsyncDataSource('role', async (field) => { + const list = roleListData; + const option = []; + for (let index = 0; index < list.items.length; index++) { + const element = list.items[index]; + const item = { + label: element.role_name, + value: element.id, + }; + option.push(item); + } + return option; + }); + }, + }); + + const getSelectData = async () => { + const list = await getRoleList({ page: 1, size: 10 }); + setRoleListData(list); + }; + + useEffect(() => { + getSelectData(); + }, []); const handleOk = async () => { form.submit(async () => { @@ -38,30 +78,6 @@ const AddAccountModal = ({ onOk, onCancel, ...rest }: AddAccountModalPropsType) onCancel(); }; - const onChange = (newValue: string[]) => {}; - - useEffect(() => { - const array = routes; - array.forEach((item: any, index) => { - if (item.name == '' || item.name == null || item.name == undefined) { - array.splice(index, 1); - console.log('array.splice(index, 1);'); - } - item.key = index + 1; - if (Object.prototype.hasOwnProperty.call(item, 'routes')) { - item.routes?.forEach((item2: any, index2: number) => { - if (item2.name == '' || item2.name == null || item2.name == undefined) { - item.routes.splice(index2, 1); - console.log('item.routes.splice(index2, 1);'); - } - item2.key = parseInt(index + 1 + '' + index2); - }); - } - }); - console.log('array = ', array); - setTreeData(array); - }, []); - return ( @@ -91,19 +107,12 @@ const AddAccountModal = ({ onOk, onCancel, ...rest }: AddAccountModalPropsType) /> diff --git a/src/pages/System/Account/components/EditAccountModal.tsx b/src/pages/System/Account/components/EditAccountModal.tsx index 4c72ce0..e22225e 100644 --- a/src/pages/System/Account/components/EditAccountModal.tsx +++ b/src/pages/System/Account/components/EditAccountModal.tsx @@ -1,12 +1,14 @@ // 创建弹窗 -import React, { useRef, useEffect } from 'react'; -import { createForm } from '@formily/core'; +import React, { useRef, useEffect, useState } from 'react'; +import { createForm, FormPathPattern, onFieldReact } from '@formily/core'; import { createSchemaField } from '@formily/react'; import Modal, { ModalProps } from '@/components/Modal'; import { Form, FormItem, Input, Select } from '@formily/antd'; -import { addUser, updateUser } from '@/services/system/accountManage'; +import { updateUser } from '@/services/system/accountManage'; +import { getRoleList } from '@/services/system/role'; +import { action } from '@formily/reactive'; -interface AddUserModalPropsType extends ModalProps { +interface EditAccountModalPropsType extends ModalProps { editModalData: any; onCancel: () => void; onOk: () => void; @@ -20,9 +22,52 @@ const SchemaField = createSchemaField({ }, }); -const form = createForm({}); +const EditAccountModal = ({ + onOk, + onCancel, + editModalData, + ...rest +}: EditAccountModalPropsType) => { + const [roleListData, setRoleListData] = useState({}); + + const getSelectData = async () => { + const list = await getRoleList({ page: 1, size: 10 }); + setRoleListData(list); + }; + + const useAsyncDataSource = ( + pattern: FormPathPattern, + service: (field: Field) => Promise<{ label: string; value: any }[]>, + ) => { + onFieldReact(pattern, (field) => { + service(field).then( + action.bound((data) => { + field.dataSource = data; + }), + ); + }); + }; + + const form = createForm({ + effects: () => { + // eslint-disable-next-line react-hooks/rules-of-hooks + useAsyncDataSource('role', async (field) => { + getSelectData(); + const list = roleListData; + const option = []; + for (let index = 0; index < list.items.length; index++) { + const element = list.items[index]; + const item = { + label: element.role_name, + value: element.id, + }; + option.push(item); + } + return option; + }); + }, + }); -const AddUserModal = ({ onOk, onCancel, editModalData, ...rest }: AddUserModalPropsType) => { useEffect(() => { form.setInitialValues(editModalData); }); @@ -32,7 +77,7 @@ const AddUserModal = ({ onOk, onCancel, editModalData, ...rest }: AddUserModalPr onOk(); const formState = form.getFormState(); formState.values.role = parseInt(formState.values.role); - await addUser(formState.values); + await updateUser(formState.values); }); }; @@ -70,7 +115,7 @@ const AddUserModal = ({ onOk, onCancel, editModalData, ...rest }: AddUserModalPr title="角色" required x-decorator="FormItem" - x-component="Input" + x-component="Select" x-component-props={{ placeholder: '请选择角色', }} @@ -81,4 +126,4 @@ const AddUserModal = ({ onOk, onCancel, editModalData, ...rest }: AddUserModalPr ); }; -export default AddUserModal; +export default EditAccountModal; diff --git a/src/pages/System/Permissions/List/index.tsx b/src/pages/System/Permissions/List/index.tsx index 68a9d00..5b46a25 100644 --- a/src/pages/System/Permissions/List/index.tsx +++ b/src/pages/System/Permissions/List/index.tsx @@ -1,54 +1,224 @@ import React, { useState, useRef } from 'react'; import Table, { ProColumns, ActionType } from '@/components/Table'; import routes from '@/routes'; +import DeleteButton from '@/components/Table/DeleteButton'; +import { getPermission, upsertPermission } from '@/services/system/permission'; +import AddPermissionModal from '../components/AddPermissionModal'; +import EditPermissionModal from '../components/EditPermissionModal'; const PermissionsList = () => { + const [isModalVisible, setIsModalVisible] = useState(false); + const [isEditModalVisible, setIsEditModalVisible] = useState(false); + + const [permissionsData, setPermissionsData] = useState(Array); + const [isAddFirst, setIsAddFirst] = useState(false); + const [modalData, setModalData] = useState({}); + const [rowData, setRowData] = useState({}); + const tableRef = useRef(); + + const handleAdd = (row: any) => { + setRowData(row); + setIsModalVisible(true); + }; + const handleEdit = (row: any) => { + setRowData(row); + setIsEditModalVisible(true); + }; + + const deleteLoopChildren = (rowData, children) => { + debugger; + for (let index = 0; index < children.length; index++) { + const childrenElement = children[index]; + if (rowData.name == childrenElement.name) { + children.splice(index, 1); + return true; + } else { + if (Object.prototype.hasOwnProperty.call(childrenElement, 'children')) { + deleteLoopChildren(rowData, childrenElement.children); + } else { + continue; + } + } + } + }; + + const handleDelete = async (row: any) => { + for (let index = 0; index < permissionsData.length; index++) { + const element = permissionsData[index]; + if (row.name == element.name) { + permissionsData.splice(index, 1); + break; + } else { + const result = deleteLoopChildren(row, element.children); + if (result) { + break; + } + } + } + await upsertPermission(permissionsData); + tableRef.current?.reload(); + }; + + const addLoopChildren = (rowData, children) => { + for (let index = 0; index < children.length; index++) { + let childrenElement = children[index]; + if (rowData.name == childrenElement.name) { + if (Object.prototype.hasOwnProperty.call(childrenElement, 'children')) { + childrenElement = rowData; + } else { + childrenElement.children = rowData; + } + return true; + } else { + if (Object.prototype.hasOwnProperty.call(childrenElement, 'children')) { + addLoopChildren(rowData, childrenElement.children); + } else { + continue; + } + } + } + }; + const editLoopChildren = (val, rowData, children) => { + for (let index = 0; index < children.length; index++) { + const childrenElement = children[index]; + if (rowData.name == childrenElement.name) { + childrenElement.name = val.name; + return true; + } else { + if (Object.prototype.hasOwnProperty.call(childrenElement, 'children')) { + editLoopChildren(val, rowData, childrenElement.children); + } else { + continue; + } + } + } + }; + const columns: ProColumns[] = [ { - title: '路由名称', + title: '权限名', dataIndex: 'name', }, - ]; - const rowSelection = { - onChange: (selectedRowKeys: React.Key[], selectedRows: DataType[]) => { - console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows); + { + title: '操作', + valueType: 'option', + width: 180, + render: (_, row) => [ + { + setIsAddFirst(false); + handleAdd(row); + }} + > + 添加 + , + { + setModalData(row); + handleEdit(row); + }} + > + 编辑 + , + Object.prototype.hasOwnProperty.call(row, 'children') ? null : ( + { + handleDelete(row); + }} + /> + ), + ], }, - }; + ]; + return (
{}, - // }, - // ]} + rowKey="name" actionRef={tableRef} + toolBarActions={[ + { + type: 'add', + onConfirm: () => { + setIsAddFirst(true); + setIsModalVisible(true); + }, + }, + ]} request={async (params) => { - const array = routes; - array.forEach((item: any, index) => { - if (item.name == '' || item.name == null || item.name == undefined) { - array.splice(index, 1); - } - item.key = index + 1; - if (Object.prototype.hasOwnProperty.call(item, 'routes')) { - item.routes?.forEach((item2: any, index2: number) => { - if (item2.name == '' || item2.name == null || item2.name == undefined) { - item.routes.splice(index2, 1); - } - item2.key = parseInt(index + 1 + '' + index2); + const res = await getPermission({}); + const data = JSON.parse(res.items); + setPermissionsData(data); + return { data: data }; + }} + /> + + diff --git a/src/pages/System/Permissions/components/AddPermissionModal.tsx b/src/pages/System/Permissions/components/AddPermissionModal.tsx new file mode 100644 index 0000000..3dc54f7 --- /dev/null +++ b/src/pages/System/Permissions/components/AddPermissionModal.tsx @@ -0,0 +1,51 @@ +// 创建弹窗 +import React, { useRef } from 'react'; +import { createForm } from '@formily/core'; +import { createSchemaField } from '@formily/react'; +import Modal, { ModalProps } from '@/components/Modal'; +import { Form, FormItem, Input } from '@formily/antd'; + +interface AddPermissionModalPropsType extends ModalProps { + onCancel: () => void; + onOk: (val: any) => void; +} + +const SchemaField = createSchemaField({ + components: { + FormItem, + Input, + }, +}); + +const form = createForm({}); + +const AddPermissionModal = ({ onOk, onCancel, ...rest }: AddPermissionModalPropsType) => { + const handleOk = async () => { + form.submit(async () => { + const formState = form.getFormState(); + onOk(formState.values); + }); + }; + + const handleCancel = () => { + onCancel(); + }; + + return ( + + + + + + + + ); +}; + +export default AddPermissionModal; diff --git a/src/pages/System/Permissions/components/EditPermissionModal.tsx b/src/pages/System/Permissions/components/EditPermissionModal.tsx new file mode 100644 index 0000000..12a8f56 --- /dev/null +++ b/src/pages/System/Permissions/components/EditPermissionModal.tsx @@ -0,0 +1,61 @@ +// 创建弹窗 +import React, { useEffect, useRef } from 'react'; +import { createForm } from '@formily/core'; +import { createSchemaField } from '@formily/react'; +import Modal, { ModalProps } from '@/components/Modal'; +import { Form, FormItem, Input } from '@formily/antd'; + +interface EditPermissionModalPropsType extends ModalProps { + editModalData: any; + onCancel: () => void; + onOk: (val: any) => void; +} + +const SchemaField = createSchemaField({ + components: { + FormItem, + Input, + }, +}); + +const form = createForm({}); + +const EditPermissionModal = ({ + onOk, + onCancel, + editModalData, + ...rest +}: EditPermissionModalPropsType) => { + useEffect(() => { + form.setInitialValues(editModalData); + }); + + const handleOk = async () => { + form.submit(async () => { + const formState = form.getFormState(); + onOk(formState.values); + }); + }; + + const handleCancel = () => { + onCancel(); + }; + + return ( + +
+ + + + +
+ ); +}; + +export default EditPermissionModal; diff --git a/src/pages/System/Role/List/index.tsx b/src/pages/System/Role/List/index.tsx index c9c4d14..05d18f2 100644 --- a/src/pages/System/Role/List/index.tsx +++ b/src/pages/System/Role/List/index.tsx @@ -1,16 +1,32 @@ -import React, { useRef } from 'react'; +import React, { useRef, useState } from 'react'; import Table, { ProColumns, ActionType } from '@/components/Table'; -import { getRoleList, deleteRole } from '@/services/system/role'; +import { getRoleList, deleteRole, createRole, updateRole } from '@/services/system/role'; import { fetchTableData } from '@/utils/table'; import DeleteButton from '@/components/Table/DeleteButton'; +import AddRoleModal from '../components/AddRoleModal'; +import EditRoleModal from '../components/EditRoleModal'; +import AuthPermissionsDrawer from '../components/AuthPermissionsDrawer'; const RoleList = () => { - const handleEdit = (row: any) => {}; - const handleAuth = (row: any) => {}; - const handleDelete = async (role: any) => { - await deleteRole({ role: role }); - }; const tableRef = useRef(); + + const [isDrawerVisible, setIsDrawerVisible] = useState(false); + const [isModalVisible, setIsModalVisible] = useState(false); + const [isEditModal, setIsEditModal] = useState(false); + const [modalData, setModalData] = useState({}); + + const handleEdit = (row: any) => { + setModalData(row); + setIsEditModal(true); + }; + const handleAuth = (row: any) => { + setIsDrawerVisible(true); + }; + const handleDelete = async (id: any) => { + await deleteRole({ id: id }); + tableRef.current?.reload(); + }; + const columns: ProColumns[] = [ { title: '角色名称', @@ -19,8 +35,8 @@ const RoleList = () => { ellipsis: true, }, { - title: '用户类型', - dataIndex: 'role', + title: '备注', + dataIndex: 'remark', hideInSearch: true, ellipsis: true, }, @@ -48,21 +64,25 @@ const RoleList = () => { { - handleDelete(row.role); + handleDelete(row.id); }} />, ], }, ]; + return (
{}, + onConfirm: () => { + setIsModalVisible(true); + }, }, ]} actionRef={tableRef} @@ -71,6 +91,38 @@ const RoleList = () => { return res; }} /> + { + await createRole(val); + setIsModalVisible(false); + tableRef.current?.reload(); + }} + /> + { + await updateRole(val); + setIsEditModal(false); + tableRef.current?.reload(); + }} + /> + ); }; diff --git a/src/pages/System/Role/components/AddRoleModal.tsx b/src/pages/System/Role/components/AddRoleModal.tsx new file mode 100644 index 0000000..5873c79 --- /dev/null +++ b/src/pages/System/Role/components/AddRoleModal.tsx @@ -0,0 +1,58 @@ +// 创建弹窗 +import React, { useRef } from 'react'; +import { createForm } from '@formily/core'; +import { createSchemaField } from '@formily/react'; +import Modal, { ModalProps } from '@/components/Modal'; +import { Form, FormItem, Input } from '@formily/antd'; + +interface AddRoleModalPropsType extends ModalProps { + onCancel: () => void; + onOk: (val: any) => void; +} + +const SchemaField = createSchemaField({ + components: { + FormItem, + Input, + }, +}); + +const form = createForm({}); + +const AddRoleModal = ({ onOk, onCancel, ...rest }: AddRoleModalPropsType) => { + const handleOk = async () => { + form.submit(async () => { + const formState = form.getFormState(); + onOk(formState.values); + }); + }; + + const handleCancel = () => { + onCancel(); + }; + + return ( + +
+ + + + + +
+ ); +}; + +export default AddRoleModal; diff --git a/src/pages/System/Role/components/AuthPermissionsDrawer.tsx b/src/pages/System/Role/components/AuthPermissionsDrawer.tsx new file mode 100644 index 0000000..bf21b95 --- /dev/null +++ b/src/pages/System/Role/components/AuthPermissionsDrawer.tsx @@ -0,0 +1,116 @@ +// 创建弹窗 +import React, { useRef, useState } from 'react'; + +import { Form, FormItem, Input } from '@formily/antd'; +import { Button, Drawer, DrawerProps, message, Space } from 'antd'; +import { ActionType, ProColumns } from '@ant-design/pro-table'; +import Table from '@/components/Table'; +import { TableRowSelection } from 'antd/lib/table/interface'; +import routes from '@/routes'; +import { getPermission } from '@/services/system/permission'; + +interface AuthPermissionsDrawerPropsType extends DrawerProps { + onCancel: () => void; + onOk: (val: any) => void; +} + +const columnsPermissions: ProColumns[] = [ + { + title: '路由名称', + dataIndex: 'name', + }, +]; + +const valueMap = {}; +function loops(list, parent) { + return (list || []).map(({ children, name }) => { + // console.log('children = ', children); + const node = (valueMap[name] = { + parent, + name, + }); + node.children = loops(children, node); + return node; + }); +} + +function getPath(name) { + const path = []; + let current = valueMap[name]; + while (current) { + path.unshift(current.name); + current = current.parent; + } + return path; +} + +const AuthPermissionsDrawer = ({ onOk, onCancel, ...rest }: AuthPermissionsDrawerPropsType) => { + const tableRef = useRef(); + const [selectedKeys, setSelectedKeys] = useState(['']); + const [postSelectedKeys, setPostSelectedKeys] = useState([]); + + const rowSelection: TableRowSelection = { + onChange: (selectedRowKeys, selectedRows) => { + setSelectedKeys(selectedRowKeys); + console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows); + }, + onSelect: (record, selected, selectedRows) => { + const path = getPath(record.name); + const newArray = selectedKeys.concat(path); + setPostSelectedKeys(newArray); + }, + // onSelectAll: (selected, selectedRows, changeRows) => { + // console.log(selected, selectedRows, changeRows); + // }, + }; + + const handleOk = () => { + if (postSelectedKeys.length == 0) { + message.warning('请选择权限。'); + return; + } + onOk(postSelectedKeys); + }; + + const handleCancel = () => { + onCancel(); + }; + + return ( + + + + + } + > +
{ + const res = await getPermission({}); + const treeData = JSON.parse(res.items); + loops(treeData, null); + return { data: treeData }; + }} + /> + + ); +}; + +export default AuthPermissionsDrawer; diff --git a/src/pages/System/Role/components/EditRoleModal.tsx b/src/pages/System/Role/components/EditRoleModal.tsx new file mode 100644 index 0000000..b72dc4f --- /dev/null +++ b/src/pages/System/Role/components/EditRoleModal.tsx @@ -0,0 +1,71 @@ +// 创建弹窗 +import React, { useRef, useEffect } from 'react'; +import { createForm } from '@formily/core'; +import { createSchemaField } from '@formily/react'; +import Modal, { ModalProps } from '@/components/Modal'; +import { Form, FormItem, Input, Select } from '@formily/antd'; +import { addUser, updateUser } from '@/services/system/accountManage'; + +interface EditRoleModalPropsType extends ModalProps { + editModalData: any; + onCancel: () => void; + onOk: (val: any) => void; +} + +const SchemaField = createSchemaField({ + components: { + FormItem, + Input, + Select, + }, +}); + +const form = createForm({}); + +const EditRoleModal = ({ onOk, onCancel, editModalData, ...rest }: EditRoleModalPropsType) => { + useEffect(() => { + form.setInitialValues(editModalData); + }); + + const handleOk = async () => { + form.submit(async () => { + const formState = form.getFormState(); + onOk(formState.values); + }); + }; + + const handleCancel = () => { + onCancel(); + }; + + return ( + +
+ + + + + +
+ ); +}; + +export default EditRoleModal; diff --git a/src/pages/document.ejs b/src/pages/document.ejs index dcaee12..e54c6ba 100644 --- a/src/pages/document.ejs +++ b/src/pages/document.ejs @@ -21,7 +21,7 @@ name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /> - Pro + TBG diff --git a/src/services/system/permission.ts b/src/services/system/permission.ts new file mode 100644 index 0000000..3521cf3 --- /dev/null +++ b/src/services/system/permission.ts @@ -0,0 +1,27 @@ +import request from '@/utils/request'; + +/** + * 获取后台权限列表 + * @param {object} params + * @returns {array} data + */ +export const getPermission = (params) => { + return request.request({ + url: '/permission/get', + method: 'get', + params, + }); +}; + +/** + * 更新后台权限列表 + * @param {object} params + * @returns {array} data + */ +export const upsertPermission = (data) => { + return request.request({ + url: '/permission/upsert', + method: 'post', + data, + }); +}; diff --git a/src/services/system/role.ts b/src/services/system/role.ts index 987ad4d..fd3e98c 100644 --- a/src/services/system/role.ts +++ b/src/services/system/role.ts @@ -9,12 +9,42 @@ import request from '@/utils/request'; */ export const getRoleList = (params) => { return request.request({ - url: '/user/role/get', + url: '/role/get', method: 'get', params, }); }; +/** + * 创建后台角色 + * @param {object} params + * role_name 角色名称 + * remark 备注 + * @returns {array} data + */ +export const createRole = (data) => { + return request.request({ + url: '/role/create', + method: 'post', + data, + }); +}; + +/** + * 更新后台角色 + * @param {object} params + * role_name 角色名称 + * remark 备注 + * @returns {array} data + */ +export const updateRole = (data) => { + return request.request({ + url: '/role/update', + method: 'post', + data, + }); +}; + /** * 删除后台角色 * @param {object} params @@ -23,7 +53,7 @@ export const getRoleList = (params) => { */ export const deleteRole = (data) => { return request.request({ - url: '/user/role/delete', + url: '/role/delete', method: 'post', data, }); diff --git a/src/utils/web3.ts b/src/utils/web3.ts index c97b085..e9b61a8 100644 --- a/src/utils/web3.ts +++ b/src/utils/web3.ts @@ -70,14 +70,13 @@ export async function transfer(abi: string, address: string, toAddress: string) const contract = new web3.eth.Contract(eval('(' + abi + ')'), address); await contract.methods .transfer(toAddress, new BigNumber(1 * Math.pow(10, 18))) - .send({ from: web3.eth.defaultAccount }), - function (error, transactionHash) { + .send({ from: web3.eth.defaultAccount }, function (error, transactionHash) { if (!error) { console.log('transactionHash is ' + transactionHash); } else { console.log(error); } - }; + }); } // NFT创建 @@ -92,17 +91,18 @@ export async function NFTMint(params: any) { if (params.toAddress == '' || params.toAddress == null || params.toAddress == undefined) { params.toAddress = web3.eth.defaultAccount; } + let tx_hash = ''; const contract = new web3.eth.Contract(eval('(' + params.abi + ')'), params.address); await contract.methods - .Mint(params.toAddress, params.token_id) - .send({ from: web3.eth.defaultAccount }), - function (error, transactionHash) { + .Mint(params.toAddress) + .send({ from: web3.eth.defaultAccount }, function (error, transactionHash) { if (!error) { - return transactionHash; + tx_hash = transactionHash; } else { console.log(error); } - }; + }); + return tx_hash; } // NFT转移