Commit f65e1c70 authored by 李腾's avatar 李腾

Merge branch 'feature/serviceGoods20220907' into 'master'

Feature/service goods20220907

See merge request !58
parents 74922b7d d3d6f4e2
...@@ -12,6 +12,7 @@ module.exports = { ...@@ -12,6 +12,7 @@ module.exports = {
'no-plusplus': ['off'], 'no-plusplus': ['off'],
'@typescript-eslint/camelcase': ['off'], '@typescript-eslint/camelcase': ['off'],
'@typescript-eslint/no-unused-vars': ['off'], '@typescript-eslint/no-unused-vars': ['off'],
'import/no-unresolved': 0,
'import/extensions': 0, 'import/extensions': 0,
}, },
}; };
...@@ -229,6 +229,36 @@ export default { ...@@ -229,6 +229,36 @@ export default {
name: 'ServiceGoods', name: 'ServiceGoods',
component: './ServiceGoods/index', component: './ServiceGoods/index',
}, },
{
title: '商户管理后台-账号管理',
path: '/systemManage/account',
name: 'systemManageAccount',
component: './systemManage/Account',
},
{
title: '商户管理后台-账号管理-用户信息',
path: '/systemManage/account/userInfo',
name: 'accountUserInfo',
component: './systemManage/Account/UserInfo',
},
{
title: '商户管理后台-角色管理',
path: '/systemManage/role',
name: 'systemManageRole',
component: './systemManage/Role',
},
{
title: '商户管理后台-角色管理-角色信息',
path: '/systemManage/role/roleInfo',
name: 'roleInfo',
component: './systemManage/Role/RoleInfo',
},
{
title: '商户管理后台-日志管理',
path: '/systemManage/log',
name: 'systemManageLog',
component: './systemManage/Log',
},
{ {
component: './404', component: './404',
}, },
......
...@@ -9,19 +9,19 @@ const envAPi = { ...@@ -9,19 +9,19 @@ const envAPi = {
// kdspOpApi: 'https://kdsp-operation-xyqb.liangkebang.net', // kdspOpApi: 'https://kdsp-operation-xyqb.liangkebang.net',
// kdspApi: 'https://sc-op-api-xyqb.liangkebang.net', // kdspApi: 'https://sc-op-api-xyqb.liangkebang.net',
// goodsApi: 'https://sc-op-api-xyqb.liangkebang.net', // goodsApi: 'https://sc-op-api-xyqb.liangkebang.net',
querysApi: 'https://sc-settlement-api-xyqb.liangkebang.net', querysApi: 'https://sc-merchant-api-sc.liangkebang.net',
// goodsApi: '//192.168.188.111:7000', // goodsApi: '//192.168.188.111:7000',
prologueDomain: 'https://mall-xyqb.liangkebang.net', prologueDomain: 'https://mall-sc.liangkebang.net',
// qiniuHost: 'https://appsync.lkbang.net', // qiniuHost: 'https://appsync.lkbang.net',
qiniuHost: 'https://kdspstatic.q-gp.com/', qiniuHost: 'https://kdspstatic.q-gp.com/',
opapiHost: 'https://opapi-xyqb.liangkebang.net', opapiHost: 'https://opapi-sc.liangkebang.net',
}; };
const prodApi = { const prodApi = {
api: '//security.q-gp.com', api: '//security.q-gp.com',
kdspOpApi: '//kdsp-operation.q-gp.com', kdspOpApi: '//kdsp-operation.q-gp.com',
prologueDomain: '//mall.q-gp.com', prologueDomain: '//mall.q-gp.com',
kdspApi: '//sc-op-api.q-gp.com', kdspApi: 'https://sc-merchant-api.q-gp.com',
// goodsApi: 'https://sc-op-api.q-gp.com', // 测试环境打包域名, // goodsApi: 'https://sc-op-api.q-gp.com', // 测试环境打包域名,
goodsApi: 'https://sc-merchant-api.q-gp.com', // 线上环境打包域名 goodsApi: 'https://sc-merchant-api.q-gp.com', // 线上环境打包域名
qiniuHost: 'https://kdspstatic.q-gp.com/', qiniuHost: 'https://kdspstatic.q-gp.com/',
......
/** @name 商品管理 */
// 商品库
export const GOOD_MANAGE = {
LIST: '020101', // 商品列表
EDITABLE: '020102', // 新增/修改
ADD_SERVICE_GOODS: '020103', // 新增服务商品
ADD_NORMAL_GOODS: '020104', // 新增实物商品
};
// 配送区域
export const DISTRIBUTION_AREA = {
LIST: '020201',
EDITABLE: '020202',
};
/** @name 订单管理 */
//待发货订单
export const PENDING_DELIVERY_ORDER = {
LIST: '020301',
EDITABLE: '020302',
};
// 已发货订单
export const DELIVERY_ORDER = {
LIST: '020401',
EDITABLE: '020402',
};
// 批量发货
export const BATCH_DELIVERY = {
LIST: '020501',
EDITABLE: '020502', // 新增/修改
};
// 订单查询
export const QUERY_ORDER = {
LIST: '020601', // 订单查询列表
EDITABLE: '020602',
};
/** @name 售后地址设置 */
export const AFTER_SALE_ADDRESS = {
LIST: '030101', // 地址列表
EDITABLE: '030102', // 新增/修改
};
/** @name 售后管理 */
export const AFTER_SALE_ORDER = {
LIST: '050101', // 售后订单列表
EDITABLE: '050102', // 新增/修改
};
/** @name 取消订单审核管理 */
export const CANCEL_BILL_MANAGE = {
LIST: '060101', // 取消订单审核列表
EDITABLE: '060102',
};
/** @name 供应商对账结算管理 */
//对账单查询
export const RECONCILIATION_QUERY = {
LIST: '070101', // 对账单列表
EDITABLE: '070102', // 新增/修改
};
// 结算单查询
export const SETTLEMENT_SHEET = {
LIST: '070201', // 结算单列表
EDITABLE: '070202', // 新增/修改
};
// 付款单查询
export const PAYMENT_MANAGE = {
LIST: '070301', // 付款单列表
EDITABLE: '070302', // 新增/修改
};
/** @name 系统管理 */
// 账号管理
export const ACCOUNT_MANAGE = {
LIST: '010101', // 账户列表
EDITABLE: '010102', // 新增/修改
};
// 角色管理
export const ROLE_MANAGE = {
LIST: '010201', // 角色列表
EDITABLE: '010202', // 新增/修改
};
...@@ -78,6 +78,11 @@ const BasicLayout = props => { ...@@ -78,6 +78,11 @@ const BasicLayout = props => {
setSiderCollapsed(payload); setSiderCollapsed(payload);
}; // get children authority }; // get children authority
// 跳转到首页
const toIndex = () => {
props.history.push('/');
};
const authorized = getAuthorityFromRouter(props.route.routes, location.pathname || '/'); const authorized = getAuthorityFromRouter(props.route.routes, location.pathname || '/');
const _menu = param => const _menu = param =>
param.map(v => param.map(v =>
...@@ -154,7 +159,7 @@ const BasicLayout = props => { ...@@ -154,7 +159,7 @@ const BasicLayout = props => {
rightContentRender={rightProps => <RightContent {...rightProps} />} rightContentRender={rightProps => <RightContent {...rightProps} />}
pageTitleRender={() => ''} pageTitleRender={() => ''}
menuHeaderRender={() => ( menuHeaderRender={() => (
<div className={style['custom-title-box']}> <div className={style['custom-title-box']} onClick={toIndex}>
<div className={style['custom-title-box-logo']}> <div className={style['custom-title-box-logo']}>
<div> <div>
<img className={style['custom-title-box-logoImg']} alt="量星球" src={logo} /> <img className={style['custom-title-box-logoImg']} alt="量星球" src={logo} />
......
import { getMenuData } from '@/services/menu'; import { getMenuData } from '@/services/menu';
import { APPLETS_PERMISSION_IDENTIFIER } from '@/utils/constants';
export const filterPermission = list => {
const permissionData = {};
const filterArr = (arr, v) => {
arr.forEach(item => {
permissionData[item.node.code] = true;
if (item.childNodes.length) {
filterArr(item.childNodes, v);
}
});
};
filterArr(list);
return permissionData;
};
const MenuModel = { const MenuModel = {
namespace: 'menu', namespace: 'menu',
...@@ -11,11 +26,13 @@ const MenuModel = { ...@@ -11,11 +26,13 @@ const MenuModel = {
key: '', key: '',
}, },
], ],
permissions: {},
}, },
effects: { effects: {
*getMenuData({ payload }, { put, call }) { *getMenuData({ payload }, { put, call }) {
const response = yield call(getMenuData, payload); const response = yield call(getMenuData, payload);
if (response.code === 2000) { if (response.code === 2000) {
// window.localStorage.setItem('permissions', JSON.stringify(response.data));
// 拿到数据后response.data后组装成新的数据复制给menuData // 拿到数据后response.data后组装成新的数据复制给menuData
yield put({ yield put({
type: 'save', type: 'save',
...@@ -30,7 +47,12 @@ const MenuModel = { ...@@ -30,7 +47,12 @@ const MenuModel = {
const value = []; const value = [];
const data = [...tableData]; const data = [...tableData];
data data
.filter(item => item.node && item.node.code !== 'applets' && item.node.type.value < 3) .filter(
item =>
item.node &&
item.node.code !== APPLETS_PERMISSION_IDENTIFIER &&
item.node.type.value < 3,
)
.forEach(item => { .forEach(item => {
let obj = {}; let obj = {};
obj = { ...item.node }; obj = { ...item.node };
...@@ -47,7 +69,19 @@ const MenuModel = { ...@@ -47,7 +69,19 @@ const MenuModel = {
return value; return value;
}; };
const menuData = initializationData(payload); const menuData = initializationData(payload);
return { ...state, menuData };
// console.log('payload', payload, JSON.parse(localStorage.getItem('permissions')))
// 设置全局权限数据rules
let { permissions } = state;
if (JSON.stringify(permissions) === '{}') {
const currentPermissions = payload;
if (currentPermissions) {
const arr = currentPermissions;
permissions = filterPermission(arr);
}
window.localStorage.setItem('permissions', JSON.stringify(permissions));
}
return { ...state, menuData, permissions };
}, },
}, },
}; };
......
...@@ -6,10 +6,18 @@ import { Link } from 'umi'; ...@@ -6,10 +6,18 @@ import { Link } from 'umi';
import { FileTextOutlined } from '@ant-design/icons'; import { FileTextOutlined } from '@ant-design/icons';
import style from './styles.less'; import style from './styles.less';
import { getPendingNum } from './service'; import { getPendingNum } from './service';
import { connect } from 'dva';
import {
AFTER_SALE_ORDER,
CANCEL_BILL_MANAGE,
PENDING_DELIVERY_ORDER,
} from '@/../config/permission.config';
const Admin = () => { const Admin = props => {
const [pendingNum, setpendingNum] = useState({}); const [pendingNum, setpendingNum] = useState({});
const showAfterSaleList = props.permissions[AFTER_SALE_ORDER.LIST];
const showCancelBillList = props.permissions[CANCEL_BILL_MANAGE.LIST];
const showPendingDeliveryOrderList = props.permissions[PENDING_DELIVERY_ORDER.LIST];
useEffect(() => { useEffect(() => {
const qurey = async () => { const qurey = async () => {
const { data } = await getPendingNum(); const { data } = await getPendingNum();
...@@ -28,63 +36,87 @@ const Admin = () => { ...@@ -28,63 +36,87 @@ const Admin = () => {
</div> </div>
<div style={{ marginTop: '20px' }}> <div style={{ marginTop: '20px' }}>
<Row className={style.orderContent}> <Row className={style.orderContent}>
<Col span={2} className="titleOne"> {showPendingDeliveryOrderList || showCancelBillList ? (
<div> <Col span={2} className="titleOne">
<FileTextOutlined /> <div>
<p>订单</p> <FileTextOutlined />
</div> <p>订单</p>
</Col> </div>
<Col span={2}> </Col>
<Link ) : (
to={{ ''
pathname: '/orderManage/pendingDeliveryOrder', )}
}}
> {showPendingDeliveryOrderList ? (
<strong>{pendingNum?.pendingShipNum || 0}</strong> <>
<p>待发货</p> <Col span={2}>
</Link> <Link
</Col> to={{
<Col span={3}> pathname: '/orderManage/pendingDeliveryOrder',
<Link }}
to={{ >
pathname: '/orderManage/pendingDeliveryOrder', <strong>{pendingNum?.pendingShipNum || 0}</strong>
state: { status: 1 }, <p>待发货</p>
}} </Link>
> </Col>
<strong>{pendingNum?.timeOutShipNum || 0}</strong> <Col span={3}>
<p>超时发货{'>'}48小时</p> <Link
</Link> to={{
</Col> pathname: '/orderManage/pendingDeliveryOrder',
<Col span={4}> state: { status: 1 },
<Link }}
to={{ >
pathname: 'cancelBillManage', <strong>{pendingNum?.timeOutShipNum || 0}</strong>
}} <p>超时发货{'>'}48小时</p>
> </Link>
<strong>{pendingNum?.cancelOrderPendingAuditNum || 0}</strong> </Col>
<p>取消订单审核{'<'}24小时</p> </>
</Link> ) : (
</Col> ''
<Col span={2} className="titleTwo" offset={4}> )}
<div> {showCancelBillList ? (
<FileTextOutlined /> <Col span={4}>
<p> 售后</p> <Link
</div> to={{
</Col> pathname: 'cancelBillManage',
<Col span={3}> }}
<Link >
to={{ <strong>{pendingNum?.cancelOrderPendingAuditNum || 0}</strong>
pathname: 'afterSaleManage', <p>取消订单审核{'<'}24小时</p>
}} </Link>
> </Col>
<strong>{pendingNum?.afterOrderPendingAuditNum || 0}</strong> ) : (
<p>退款待审核{'<'}24小时</p> ''
</Link> )}
</Col> {showAfterSaleList ? (
<>
<Col span={2} className="titleTwo" offset={4}>
<div>
<FileTextOutlined />
<p> 售后</p>
</div>
</Col>
<Col span={3}>
<Link
to={{
pathname: 'afterSaleManage',
}}
>
<strong>{pendingNum?.afterOrderPendingAuditNum || 0}</strong>
<p>退款待审核{'<'}24小时</p>
</Link>
</Col>
</>
) : (
''
)}
</Row> </Row>
</div> </div>
</div> </div>
</div> </div>
); );
}; };
export default Admin; export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(Admin);
...@@ -11,7 +11,8 @@ import LogisticsCom from '../../orderManage/pendingDeliveryOrder/components/Logi ...@@ -11,7 +11,8 @@ import LogisticsCom from '../../orderManage/pendingDeliveryOrder/components/Logi
import AppealDetail from '../../afterSale/components/detail'; import AppealDetail from '../../afterSale/components/detail';
import AfterLog from '../components/AfterLog'; import AfterLog from '../components/AfterLog';
export default () => { export default props => {
const { canEditable } = props;
const table = useRef(); const table = useRef();
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [detailVisible, setDetailVisible] = useState(false); const [detailVisible, setDetailVisible] = useState(false);
...@@ -165,10 +166,20 @@ export default () => { ...@@ -165,10 +166,20 @@ export default () => {
</Button>, </Button>,
]; ];
// 服务订单删除物流拦截 // 没权限返回详情、查看物流、查看记录
if (!canEditable) {
// 服务订单返回订单详情和查看记录
if (!['vip', 'self'].includes(r.supplierType)) {
return [operations[2], operations[4]];
}
return [operations[2], operations[3], operations[4]];
}
// 有权限 服务订单 不反返回物流
if (!['vip', 'self'].includes(r.supplierType)) { if (!['vip', 'self'].includes(r.supplierType)) {
operations.splice(3, 1); return [operations[0], operations[1], operations[2], operations[4]];
} }
// 有修改权限&&非服务订单 全部返回
return operations; return operations;
}, },
}, },
......
...@@ -16,7 +16,8 @@ import styles from '../styles.less'; ...@@ -16,7 +16,8 @@ import styles from '../styles.less';
const { Countdown } = Statistic; const { Countdown } = Statistic;
const { confirm } = Modal; const { confirm } = Modal;
export default () => { export default props => {
const { canEditable } = props;
const table = useRef(); const table = useRef();
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [detailVisible, setDetailVisible] = useState(false); const [detailVisible, setDetailVisible] = useState(false);
...@@ -167,9 +168,14 @@ export default () => { ...@@ -167,9 +168,14 @@ export default () => {
</Button>, </Button>,
]; ];
// 不可编辑直接隐藏可操作按钮
if (!canEditable) {
return [operations[2], operations[3]];
}
// 服务订单删除物流拦截 // 服务订单删除物流拦截
if (!['vip', 'self'].includes(r.supplierType)) { if (!['vip', 'self'].includes(r.supplierType)) {
operations.splice(1, 1); return [operations[0], operations[2], operations[3]];
} }
return operations; return operations;
}, },
......
import { Tabs } from 'antd'; import { Tabs } from 'antd';
import React from 'react'; import React from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { AFTER_SALE_ORDER } from '@/../config/permission.config';
import { connect } from 'dva';
import Pending from './Pending'; import Pending from './Pending';
import PassAudit from './PassAudit'; import PassAudit from './PassAudit';
const { TabPane } = Tabs; const { TabPane } = Tabs;
export default function AfterSale() { function AfterSale(props) {
const { permissions } = props;
const canEditable = permissions[AFTER_SALE_ORDER.EDITABLE];
return ( return (
<PageHeaderWrapper> <PageHeaderWrapper>
<Tabs defaultActiveKey="1"> <Tabs defaultActiveKey="1">
<TabPane tab="未审核" key="1"> <TabPane tab="未审核" key="1">
<Pending /> <Pending canEditable={canEditable} />
</TabPane> </TabPane>
<TabPane tab="已审核" key="2"> <TabPane tab="已审核" key="2">
<PassAudit /> <PassAudit canEditable={canEditable} />
</TabPane> </TabPane>
</Tabs> </Tabs>
</PageHeaderWrapper> </PageHeaderWrapper>
); );
} }
export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(AfterSale);
...@@ -18,11 +18,13 @@ import { format } from 'date-fns'; ...@@ -18,11 +18,13 @@ import { format } from 'date-fns';
import styles from '../style.less'; import styles from '../style.less';
import { stateList } from '../staticdata'; import { stateList } from '../staticdata';
import { apiGoodsInfosExport } from '../service'; import { apiGoodsInfosExport } from '../service';
import { GOOD_MANAGE } from '@/../config/permission.config';
const FormItem = Form.Item; const FormItem = Form.Item;
const { Option } = Select; const { Option } = Select;
@connect(({ goodsManage }) => ({ @connect(({ goodsManage, menu }) => ({
goodsManage, goodsManage,
permissions: menu.permissions,
})) }))
class goodsManage extends Component { class goodsManage extends Component {
formRef = React.createRef(); formRef = React.createRef();
...@@ -95,10 +97,11 @@ class goodsManage extends Component { ...@@ -95,10 +97,11 @@ class goodsManage extends Component {
}; };
render() { render() {
const { treeData } = this.props; const { treeData, permissions } = this.props;
const selectW = { width: 250 }; const selectW = { width: 250 };
const iptNumWidth = { width: 118 }; const iptNumWidth = { width: 118 };
const that = this; const that = this;
const canEditable = permissions[GOOD_MANAGE.EDITABLE];
const content = ( const content = (
<div> <div>
<Button style={{ border: 'none' }} onClick={() => this.setArea(1, 'distribution')}> <Button style={{ border: 'none' }} onClick={() => this.setArea(1, 'distribution')}>
...@@ -220,14 +223,15 @@ class goodsManage extends Component { ...@@ -220,14 +223,15 @@ class goodsManage extends Component {
导出 导出
</Button> </Button>
</FormItem> </FormItem>
<FormItem style={{ float: 'right' }}> {canEditable ? (
<Popover content={content} onVisibleChange={this.handleVisibleChange}> <FormItem style={{ float: 'right' }}>
<Button type="primary" className={styles.button}> <Popover content={content} onVisibleChange={this.handleVisibleChange}>
批量设置 <Button type="primary" className={styles.button}>
</Button> 批量设置
</Popover> </Button>
{this.props.selectNum > 0 && <Tag color="green">已选商品 {this.props.selectNum}</Tag>} </Popover>
{/* <Button {this.props.selectNum > 0 && <Tag color="green">已选商品 {this.props.selectNum}</Tag>}
{/* <Button
className={styles.button} className={styles.button}
type="primary" type="primary"
icon="download" icon="download"
...@@ -243,7 +247,10 @@ class goodsManage extends Component { ...@@ -243,7 +247,10 @@ class goodsManage extends Component {
批量库存修改 批量库存修改
</Button> </Button>
</Upload> */} </Upload> */}
</FormItem> </FormItem>
) : (
''
)}
</Form> </Form>
); );
} }
......
...@@ -28,8 +28,11 @@ import SearchForm from './SearchForm'; ...@@ -28,8 +28,11 @@ import SearchForm from './SearchForm';
import TempleatModal from './TempleatModal'; import TempleatModal from './TempleatModal';
import ServiceGoods from '../ServiceGoods'; import ServiceGoods from '../ServiceGoods';
@connect(({ goodsManage }) => ({ import { GOOD_MANAGE } from '@/../config/permission.config';
@connect(({ goodsManage, menu }) => ({
goodsManage, goodsManage,
permissions: menu.permissions,
})) }))
class goodsManage extends Component { class goodsManage extends Component {
state = { state = {
...@@ -385,29 +388,42 @@ class goodsManage extends Component { ...@@ -385,29 +388,42 @@ class goodsManage extends Component {
render() { render() {
const { const {
goodsManage: { tableData = {} }, goodsManage: { tableData = {} },
permissions,
} = this.props; } = this.props;
const rowSelection = { const rowSelection = {
selectedRowKeys: this.state.selectedRowKeys, selectedRowKeys: this.state.selectedRowKeys,
onChange: this.onSelectChange, onChange: this.onSelectChange,
}; };
const { pageNo, pageSize, selectedRowKeys } = this.state; const { pageNo, pageSize, selectedRowKeys } = this.state;
const canAddService = permissions[GOOD_MANAGE.ADD_SERVICE_GOODS];
const canAddNormal = permissions[GOOD_MANAGE.ADD_NORMAL_GOODS];
return ( return (
<PageHeaderWrapper> <PageHeaderWrapper>
<Spin spinning={this.state.createloading}> <Spin spinning={this.state.createloading}>
<Button {canAddNormal ? (
type="primary" <Button
className={styles.button} type="primary"
onClick={() => this.setState({ createVisible: true, initData: {} })} className={styles.button}
> onClick={() => this.setState({ createVisible: true, initData: {} })}
新增商品 >
</Button> 新增商品
<Button </Button>
type="primary" ) : (
className={styles.button} ''
onClick={() => this.serviceVisbleClose(true)} )}
> {canAddService ? (
新增服务类商品 <Button
</Button> type="primary"
className={styles.button}
onClick={() => this.serviceVisbleClose(true)}
>
新增服务类商品
</Button>
) : (
''
)}
<Card> <Card>
<SearchForm <SearchForm
handleSearch={this.handleSearch} handleSearch={this.handleSearch}
......
...@@ -194,7 +194,7 @@ export function column() { ...@@ -194,7 +194,7 @@ export function column() {
align: 'center', align: 'center',
render: (_, row) => ( render: (_, row) => (
<div className={styles.actionBtn}> <div className={styles.actionBtn}>
{(row.state === 4 || (row.state >= 5 && row.updateState !== 1)) && ( {this.canEditable && (row.state === 4 || (row.state >= 5 && row.updateState !== 1)) && (
<Button <Button
key="edit" key="edit"
type="primary" type="primary"
......
...@@ -147,24 +147,33 @@ export function columns(res, pages) { ...@@ -147,24 +147,33 @@ export function columns(res, pages) {
fixed: 'right', fixed: 'right',
render: (_, row) => ( render: (_, row) => (
<div> <div>
<Button {res.canEditable ? (
type="primary" <>
disabled={row.payState !== 1} <Button
className={styles.button} type="primary"
onClick={() => res.edit(0, row)} disabled={row.payState !== 1}
> className={styles.button}
申请结算 onClick={() => res.edit(0, row)}
</Button> >
<Button 申请结算
type="primary" </Button>
disabled={ <Button
!((row.blueInvoiceState === 1 || row.blueInvoiceState === 3) && row.payState === 3) type="primary"
} disabled={
className={styles.button} !(
onClick={() => res.edit(1, row)} (row.blueInvoiceState === 1 || row.blueInvoiceState === 3) &&
> row.payState === 3
上传发票 )
</Button> }
className={styles.button}
onClick={() => res.edit(1, row)}
>
上传发票
</Button>
</>
) : (
''
)}
<Button <Button
type="primary" type="primary"
disabled={row.blueInvoiceState === 1} disabled={row.blueInvoiceState === 1}
......
...@@ -7,6 +7,8 @@ import ProTable from '@ant-design/pro-table'; ...@@ -7,6 +7,8 @@ import ProTable from '@ant-design/pro-table';
import { saveAs } from 'file-saver'; import { saveAs } from 'file-saver';
import { format } from 'date-fns'; import { format } from 'date-fns';
import moment from 'moment'; import moment from 'moment';
import { connect } from 'dva';
import { PAYMENT_MANAGE } from '@/../config/permission.config';
import ToExamineModal from './ToExamine'; import ToExamineModal from './ToExamine';
import { columns, toolBarRender } from './data'; import { columns, toolBarRender } from './data';
import { import {
...@@ -19,7 +21,9 @@ import { ...@@ -19,7 +21,9 @@ import {
const { confirm } = Modal; const { confirm } = Modal;
const PaymentMange = () => { const PaymentMange = props => {
const { permissions } = props;
const canEditable = permissions[PAYMENT_MANAGE.EDITABLE];
const actionRef = useRef(); const actionRef = useRef();
const formRef = useRef(); const formRef = useRef();
const [toExamineData, settoExamineData] = useState({}); const [toExamineData, settoExamineData] = useState({});
...@@ -125,6 +129,7 @@ const PaymentMange = () => { ...@@ -125,6 +129,7 @@ const PaymentMange = () => {
const res = { const res = {
edit, edit,
canEditable,
}; };
const searchRender = ({ searchText, resetText }, { form }) => [ const searchRender = ({ searchText, resetText }, { form }) => [
...@@ -199,4 +204,6 @@ const PaymentMange = () => { ...@@ -199,4 +204,6 @@ const PaymentMange = () => {
); );
}; };
export default PaymentMange; export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(PaymentMange);
...@@ -88,13 +88,17 @@ export function columns(pages) { ...@@ -88,13 +88,17 @@ export function columns(pages) {
} }
export const toolBarRender = gather => { export const toolBarRender = gather => {
const { onDownload, confirmAction } = gather; const { onDownload, confirmAction, canEditable } = gather;
return () => [ return () => [
<Button type="primary" style={{ marginRight: '20px' }} onClick={onDownload}> <Button type="primary" style={{ marginRight: '20px' }} onClick={onDownload}>
下载 下载
</Button>, </Button>,
<Button type="primary" onClick={confirmAction}> canEditable ? (
确认 <Button type="primary" onClick={confirmAction}>
</Button>, 确认
</Button>
) : (
''
),
]; ];
}; };
...@@ -5,10 +5,15 @@ import { PageHeaderWrapper } from '@ant-design/pro-layout'; ...@@ -5,10 +5,15 @@ import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table';
import { saveAs } from 'file-saver'; import { saveAs } from 'file-saver';
import { format } from 'date-fns'; import { format } from 'date-fns';
import { connect } from 'dva';
import { RECONCILIATION_QUERY } from '@/../config/permission.config';
import { columns, toolBarRender } from './data'; import { columns, toolBarRender } from './data';
import { query, confirmSelfBill, downloadSelfBillDetail } from './service'; import { query, confirmSelfBill, downloadSelfBillDetail } from './service';
const ReconciliationQuery = () => { const ReconciliationQuery = props => {
const { permissions } = props;
const canEditable = permissions[RECONCILIATION_QUERY.EDITABLE];
const actionRef = useRef(); const actionRef = useRef();
const [selectedRowKeys, setselectedRowKeys] = useState([]); const [selectedRowKeys, setselectedRowKeys] = useState([]);
const [selectedRows, setselectedRows] = useState([]); const [selectedRows, setselectedRows] = useState([]);
...@@ -105,6 +110,7 @@ const ReconciliationQuery = () => { ...@@ -105,6 +110,7 @@ const ReconciliationQuery = () => {
const gather = { const gather = {
onDownload, onDownload,
confirmAction, confirmAction,
canEditable,
}; };
const onToolBarRender = toolBarRender(gather); const onToolBarRender = toolBarRender(gather);
...@@ -161,4 +167,6 @@ const ReconciliationQuery = () => { ...@@ -161,4 +167,6 @@ const ReconciliationQuery = () => {
); );
}; };
export default ReconciliationQuery; export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(ReconciliationQuery);
...@@ -124,8 +124,12 @@ export function columns(pages) { ...@@ -124,8 +124,12 @@ export function columns(pages) {
]; ];
} }
export const toolBarRender = paymentOrder => () => [ export const toolBarRender = ({ paymentOrder, canEditable }) => () => [
<Button type="primary" onClick={paymentOrder}> canEditable ? (
生成付款单 <Button type="primary" onClick={paymentOrder}>
</Button>, 生成付款单
</Button>
) : (
<></>
),
]; ];
...@@ -5,10 +5,14 @@ import { Button, Upload, notification, Spin } from 'antd'; ...@@ -5,10 +5,14 @@ import { Button, Upload, notification, Spin } from 'antd';
import React, { useRef, useEffect, useState } from 'react'; import React, { useRef, useEffect, useState } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table';
import { connect } from 'dva';
import { columns, toolBarRender, dateStateEnum } from './data'; import { columns, toolBarRender, dateStateEnum } from './data';
import { query, selfPaymentBill } from './service'; import { query, selfPaymentBill } from './service';
import { SETTLEMENT_SHEET } from '@/../config/permission.config';
const SettlementSheet = () => { const SettlementSheet = props => {
const { permissions } = props;
const canEditable = permissions[SETTLEMENT_SHEET.EDITABLE];
const actionRef = useRef(); const actionRef = useRef();
const [selectedRowKeys, setselectedRowKeys] = useState([]); const [selectedRowKeys, setselectedRowKeys] = useState([]);
const [selectedRowsList, setselectedRowsList] = useState([]); const [selectedRowsList, setselectedRowsList] = useState([]);
...@@ -107,7 +111,7 @@ const SettlementSheet = () => { ...@@ -107,7 +111,7 @@ const SettlementSheet = () => {
return data; return data;
}; };
const onToolBarRender = toolBarRender(paymentOrder); const onToolBarRender = toolBarRender({ paymentOrder, canEditable });
const rowSelection = { const rowSelection = {
selectedRowKeys, selectedRowKeys,
...@@ -164,4 +168,6 @@ const SettlementSheet = () => { ...@@ -164,4 +168,6 @@ const SettlementSheet = () => {
); );
}; };
export default SettlementSheet; export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(SettlementSheet);
...@@ -3,13 +3,17 @@ import React, { useRef, useEffect, useState } from 'react'; ...@@ -3,13 +3,17 @@ import React, { useRef, useEffect, useState } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table';
import lodash from 'lodash'; import lodash from 'lodash';
import { connect } from 'dva';
import { AFTER_SALE_ADDRESS } from '@/../config/permission.config';
import styles from './index.less'; import styles from './index.less';
import AddrForm from './form'; import AddrForm from './form';
import { del, query, supplier } from './services'; import { del, query, supplier } from './services';
const { Option } = Select; const { Option } = Select;
const TableList = () => { const TableList = props => {
const { permissions } = props;
const canEditable = permissions[AFTER_SALE_ADDRESS.EDITABLE];
const [supplierList, setSupplierList] = useState([]); const [supplierList, setSupplierList] = useState([]);
const [shopId, setShopId] = useState(null); const [shopId, setShopId] = useState(null);
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
...@@ -143,30 +147,35 @@ const TableList = () => { ...@@ -143,30 +147,35 @@ const TableList = () => {
dataIndex: 'option', dataIndex: 'option',
key: 'option', key: 'option',
valueType: 'option', valueType: 'option',
render: (_, row) => [ render: (_, row) => {
<Button if (canEditable) {
key="edit" return [
type="primary" <Button
onClick={() => { key="edit"
editAction(row); type="primary"
}} onClick={() => {
> editAction(row);
修改 }}
</Button>, >
<Popconfirm 修改
placement="topLeft" </Button>,
title="确定要删除吗?" <Popconfirm
onConfirm={() => { placement="topLeft"
delAction(row); title="确定要删除吗?"
}} onConfirm={() => {
okText="删除" delAction(row);
cancelText="取消" }}
> okText="删除"
<Button key="del" type="danger" className={styles.btn}> cancelText="取消"
删除 >
</Button> <Button key="del" type="danger" className={styles.btn}>
</Popconfirm>, 删除
], </Button>
</Popconfirm>,
];
}
return [];
},
}, },
]; ];
return ( return (
...@@ -181,9 +190,13 @@ const TableList = () => { ...@@ -181,9 +190,13 @@ const TableList = () => {
bordered bordered
scroll={{ x: 1500 }} scroll={{ x: 1500 }}
toolBarRender={() => [ toolBarRender={() => [
<Button key="3" type="primary" onClick={addAction}> canEditable ? (
添加售后地址 <Button key="3" type="primary" onClick={addAction}>
</Button>, 添加售后地址
</Button>
) : (
<></>
),
]} ]}
onReset={() => reload('reset')} onReset={() => reload('reset')}
/> />
...@@ -197,4 +210,6 @@ const TableList = () => { ...@@ -197,4 +210,6 @@ const TableList = () => {
); );
}; };
export default TableList; export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(TableList);
...@@ -12,7 +12,8 @@ import AuditModal from './components/auditModal'; ...@@ -12,7 +12,8 @@ import AuditModal from './components/auditModal';
import DetailTable from './components/detailTable'; import DetailTable from './components/detailTable';
import { dateDiff } from './common'; import { dateDiff } from './common';
export default () => { export default props => {
const { canEditable } = props;
const table = useRef(); const table = useRef();
const ref = useRef(); const ref = useRef();
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
...@@ -148,14 +149,23 @@ export default () => { ...@@ -148,14 +149,23 @@ export default () => {
width: 250, width: 250,
fixed: 'right', fixed: 'right',
// eslint-disable-next-line no-shadow // eslint-disable-next-line no-shadow
render: (_, r) => [ render: (_, r) => {
<Button key="link1" onClick={() => openAudit(r)} className="mr10" type="primary"> const examine = (
审核 <Button key="link1" onClick={() => openAudit(r)} className="mr10" type="primary">
</Button>, 审核
<Button key="link" onClick={() => viewDetail(r)} type="primary"> </Button>
订单详情 );
</Button>, const detail = (
], <Button key="link" onClick={() => viewDetail(r)} type="primary">
订单详情
</Button>
);
if (!canEditable) {
return [detail];
}
return [examine, detail];
},
}, },
]; ];
return ( return (
......
import { Tabs } from 'antd'; import { Tabs } from 'antd';
import React from 'react'; import React from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { connect } from 'dva';
import { CANCEL_BILL_MANAGE } from '@/../config/permission.config';
import Pending from './Pending'; import Pending from './Pending';
import PassAudit from './PassAudit'; import PassAudit from './PassAudit';
const { TabPane } = Tabs; const { TabPane } = Tabs;
export default function CancelBillManage() { function CancelBillManage(props) {
const { permissions } = props;
const canEditable = permissions[CANCEL_BILL_MANAGE.EDITABLE];
// const [tabKey, setTabKey] = useState({}); // const [tabKey, setTabKey] = useState({});
// const changeTab = () => { // const changeTab = () => {
// const key = tabKey + 1; // const key = tabKey + 1;
// setTabKey(key) // setTabKey(key)
// } // }
console.log('permissions', canEditable);
return ( return (
<PageHeaderWrapper> <PageHeaderWrapper>
<Tabs defaultActiveKey="1"> <Tabs defaultActiveKey="1">
<TabPane tab="未审核" key="1"> <TabPane tab="未审核" key="1">
<Pending /> <Pending canEditable={canEditable} />
</TabPane> </TabPane>
<TabPane tab="已审核" key="2"> <TabPane tab="已审核" key="2">
<PassAudit /> <PassAudit canEditable={canEditable} />
</TabPane> </TabPane>
</Tabs> </Tabs>
</PageHeaderWrapper> </PageHeaderWrapper>
); );
} }
export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(CancelBillManage);
...@@ -119,6 +119,7 @@ export default () => { ...@@ -119,6 +119,7 @@ export default () => {
const onPageChange = (e, size) => { const onPageChange = (e, size) => {
setPageNo(e); setPageNo(e);
setPageSize(size); setPageSize(size);
onSearch(refSearch.current?.getFieldValue?.() || {});
}; };
useEffect(() => { useEffect(() => {
......
...@@ -41,16 +41,21 @@ export function columns(res) { ...@@ -41,16 +41,21 @@ export function columns(res) {
key: 'option', key: 'option',
align: 'center', align: 'center',
width: 100, width: 100,
render: (_, row) => ( render: (_, row) => {
<div className={styles.option}> if (!res.canEditable) {
<Button type="primary" onClick={() => res.edit(0, row)}> return '-';
复制 }
</Button> return (
<Button type="primary" onClick={() => res.edit(1, row)}> <div className={styles.option}>
编辑 <Button type="primary" onClick={() => res.edit(0, row)}>
</Button> 复制
</div> </Button>
), <Button type="primary" onClick={() => res.edit(1, row)}>
编辑
</Button>
</div>
);
},
}, },
]; ];
} }
...@@ -2,11 +2,15 @@ import { Button, Popconfirm, notification } from 'antd'; ...@@ -2,11 +2,15 @@ import { Button, Popconfirm, notification } from 'antd';
import React, { useRef, useEffect, useState } from 'react'; import React, { useRef, useEffect, useState } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table';
import { connect } from 'dva';
import { columns } from './data'; import { columns } from './data';
import AddArea from './addArea'; import AddArea from './addArea';
import { searchList, addressTree } from './services'; import { searchList, addressTree } from './services';
import { DISTRIBUTION_AREA } from '@/../config/permission.config';
const TableList = () => { const TableList = props => {
const { permissions } = props;
const canEditable = permissions[DISTRIBUTION_AREA.EDITABLE];
const [visible, setVisible] = useState(false); const [visible, setVisible] = useState(false);
const [templateData, settemplateData] = useState(''); const [templateData, settemplateData] = useState('');
const actionRef = useRef(); const actionRef = useRef();
...@@ -29,6 +33,7 @@ const TableList = () => { ...@@ -29,6 +33,7 @@ const TableList = () => {
}; };
const res = { const res = {
edit, edit,
canEditable,
}; };
useEffect(() => {}, []); useEffect(() => {}, []);
return ( return (
...@@ -42,9 +47,12 @@ const TableList = () => { ...@@ -42,9 +47,12 @@ const TableList = () => {
search={false} search={false}
options={false} options={false}
toolBarRender={() => [ toolBarRender={() => [
<Button key="3" type="primary" onClick={setaArea}> canEditable && (
添加 <Button key="3" type="primary" onClick={setaArea}>
</Button>, {' '}
添加
</Button>
),
]} ]}
/> />
<AddArea visible={visible} onSubmit={reload} templateData={templateData} /> <AddArea visible={visible} onSubmit={reload} templateData={templateData} />
...@@ -52,4 +60,6 @@ const TableList = () => { ...@@ -52,4 +60,6 @@ const TableList = () => {
); );
}; };
export default TableList; export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(TableList);
...@@ -2,6 +2,8 @@ import { Button, Upload, notification } from 'antd'; ...@@ -2,6 +2,8 @@ import { Button, Upload, notification } from 'antd';
import React, { useRef } from 'react'; import React, { useRef } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table';
import { connect } from 'dva';
import { BATCH_DELIVERY } from '@/../config/permission.config';
import { import {
queryToBatchSend, queryToBatchSend,
uploadFile, uploadFile,
...@@ -9,8 +11,10 @@ import { ...@@ -9,8 +11,10 @@ import {
downUploadeOrder, downUploadeOrder,
} from '../pendingDeliveryOrder/service'; } from '../pendingDeliveryOrder/service';
const TableList = ref => { const TableList = props => {
const actionRef = useRef(null); const actionRef = useRef(null);
const { permissions } = props;
const canEditable = permissions[BATCH_DELIVERY.EDITABLE];
const columns = [ const columns = [
{ {
...@@ -147,6 +151,9 @@ const TableList = ref => { ...@@ -147,6 +151,9 @@ const TableList = ref => {
模板下载 模板下载
</Button>, </Button>,
]; ];
if (!canEditable) {
exportBtn.splice(0, 1);
}
return [ return [
<Button <Button
key="search" key="search"
...@@ -192,4 +199,6 @@ const TableList = ref => { ...@@ -192,4 +199,6 @@ const TableList = ref => {
); );
}; };
export default TableList; export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(TableList);
...@@ -4,6 +4,8 @@ import { PageHeaderWrapper } from '@ant-design/pro-layout'; ...@@ -4,6 +4,8 @@ import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table'; import ProTable from '@ant-design/pro-table';
import { FormInstance } from 'antd/lib/form'; import { FormInstance } from 'antd/lib/form';
import moment from 'moment'; import moment from 'moment';
import { connect } from 'dva';
import { PENDING_DELIVERY_ORDER, DELIVERY_ORDER } from '@/../config/permission.config';
import LogisticsForm from './components/LogisticsForm'; import LogisticsForm from './components/LogisticsForm';
import style from './styles.less'; import style from './styles.less';
import PopoverDom from './components/PreviewImage'; import PopoverDom from './components/PreviewImage';
...@@ -22,6 +24,10 @@ const { confirm } = Modal; ...@@ -22,6 +24,10 @@ const { confirm } = Modal;
const TableList = props => { const TableList = props => {
const dateFormat = 'YYYY-MM-DD'; const dateFormat = 'YYYY-MM-DD';
const { permissions } = props;
// 因待发货 和 已发货都使用当前组件,功能且相同,所以只要授权其中一个均可获得发货物流权限
const canEditable =
permissions[PENDING_DELIVERY_ORDER.EDITABLE] || permissions[DELIVERY_ORDER.EDITABLE];
const [companys, setCompanys] = useState([]); const [companys, setCompanys] = useState([]);
const [LogisticsModalVisible, handleModalVisible] = useState(false); const [LogisticsModalVisible, handleModalVisible] = useState(false);
const [skuList, setSkuList] = useState([]); const [skuList, setSkuList] = useState([]);
...@@ -299,7 +305,7 @@ const TableList = props => { ...@@ -299,7 +305,7 @@ const TableList = props => {
fixed: 'right', fixed: 'right',
render: (_, record) => ( render: (_, record) => (
<React.Fragment> <React.Fragment>
{ShowUpdateBtn.includes(record?.skuSource?.value) ? null : ( {canEditable && ShowUpdateBtn.includes(record?.skuSource?.value) ? null : (
<Button <Button
type="primary" type="primary"
style={{ style={{
...@@ -324,7 +330,7 @@ const TableList = props => { ...@@ -324,7 +330,7 @@ const TableList = props => {
{props.type === 2 ? '更新物流信息' : '填写物流信息'} {props.type === 2 ? '更新物流信息' : '填写物流信息'}
</Button> </Button>
)} )}
{props.type !== 2 && ( {canEditable && props.type !== 2 && (
<Button <Button
type="primary" type="primary"
className={+record.delayStatus === 1 ? style.btnWarning : ''} className={+record.delayStatus === 1 ? style.btnWarning : ''}
...@@ -453,4 +459,6 @@ const TableList = props => { ...@@ -453,4 +459,6 @@ const TableList = props => {
); );
}; };
export default TableList; export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(TableList);
import { Form, Tabs, Input, Button, Pagination } from 'antd'; import { Form, Tabs, Input, Button, Pagination } from 'antd';
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { PageHeaderWrapper } from '@ant-design/pro-layout'; import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { connect } from 'dva';
import { QUERY_ORDER } from '@/../config/permission.config';
import style from './index.less'; import style from './index.less';
import { CustomTable } from './components/CustomTable/index'; import { CustomTable } from './components/CustomTable/index';
import { FormSearch, SEARCH_TYPE } from './components/FormSearch/index'; import { FormSearch, SEARCH_TYPE } from './components/FormSearch/index';
...@@ -13,7 +15,9 @@ import { ORDER_SEARCH_TYPE, ORDER_TYPE, ORDER_STATUS } from './const'; ...@@ -13,7 +15,9 @@ import { ORDER_SEARCH_TYPE, ORDER_TYPE, ORDER_STATUS } from './const';
const { TabPane } = Tabs; const { TabPane } = Tabs;
const OrderList = ref => { const OrderList = props => {
const { permissions } = props;
const canEditable = permissions[QUERY_ORDER.EDITABLE];
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const detailModalRef = useRef(); const detailModalRef = useRef();
...@@ -290,6 +294,9 @@ const OrderList = ref => { ...@@ -290,6 +294,9 @@ const OrderList = ref => {
align: 'center', align: 'center',
width: 100, width: 100,
render: ({ value, record, index, subRecord, subIndex }) => { render: ({ value, record, index, subRecord, subIndex }) => {
if (!canEditable) {
return '-';
}
let text = ''; let text = '';
if ([12, 14].includes(record.orderStatus)) { if ([12, 14].includes(record.orderStatus)) {
...@@ -412,4 +419,6 @@ const OrderList = ref => { ...@@ -412,4 +419,6 @@ const OrderList = ref => {
</PageHeaderWrapper> </PageHeaderWrapper>
); );
}; };
export default OrderList; export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(OrderList);
import React, { useRef, useState, useEffect } from 'react';
import { Input, Checkbox, Radio, Button, notification, Spin } from 'antd';
import { Form } from '@ant-design/compatible';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import RolePermissionsModal from '../components/RolePermissionsModal';
import { getRoleList, addUser, getUserDetail, updateUser } from '../../service';
import { shopGetBySupplierId } from '@/pages/ServiceGoods/service';
import UUID from '@/utils/uuid';
import style from './index.less';
const AccountInfo = props => {
const { getFieldDecorator, validateFields, getFieldValue, setFieldsValue } = props.form;
const { id } = props.location.query;
const [title, setTitle] = useState('新增用户');
const [inputType, setInputType] = useState('text');
const [confirmInputType, setConfirmInputType] = useState('text');
const [roleList, setRoleList] = useState([]);
const [supplierList, setSupplierList] = useState([]);
const [detailInfo, setDetailInfo] = useState({});
const [loading, setLoading] = useState(false);
const userInfo = JSON.parse(localStorage.getItem('user') || '{}');
const rolePermissionsModalRef = useRef();
const popReg = /^pop_/g;
const isPop = popReg.test(userInfo.supplierCode);
// 表单布局
const formLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 12 },
};
const btnLayout = {
wrapperCol: { offset: 4, span: 12 },
};
const handleConfirmPassword = (rule, value, callback) => {
if (value && value !== getFieldValue('password')) {
callback('两次输入不一致!');
}
callback();
};
// 表单验证
const formRules = {
account: [
{ required: true, message: '请设置登录用户名' },
{ pattern: /^[a-zA-Z0-9@.]{1,32}$/g, message: '用户名格式错误' },
],
name: [{ required: true, message: '请输入姓名' }],
password: [
{ required: true, message: '请设置密码' },
{
pattern: /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[\W_]).{13,18}$/g,
message: '密码格式错误',
},
],
confirmPassword: [
{ required: true, message: '请确认登录密码' },
{ validator: handleConfirmPassword, message: '两次密码不一致' },
],
roleId: [{ required: true, type: 'array', message: '请选择用户角色' }],
};
// 角色权限 modal
const openRolePermissionsModal = record => {
rolePermissionsModalRef.current.open(record);
};
// 获取所有门店列表
const getAllSupplier = res => {
if (res.code !== '0000') {
notification.warning({
message: res.detail,
});
return;
}
setSupplierList(res.data);
};
// 获取所有角色列表
const getAllRoleList = res => {
if (res.code !== 2000) {
notification.warning({ message: res.detail });
return;
}
console.log(res);
const { content } = res.data;
setRoleList(content);
};
// 获取当前选中的角色id
const getSelectedRoleIds = () => {
const cacheIds = window.sessionStorage.getItem('_selectedRoleIds');
return cacheIds ? JSON.parse(cacheIds) : [];
};
// 获取账户详情
const getAccountDetail = res => {
setLoading(false);
if (res.code !== 2000) {
notification.warning({ message: res.detail });
return;
}
console.log(res);
setDetailInfo(res.data);
const { account, name, organization } = res.data;
const roleId = getSelectedRoleIds();
console.log(roleId);
setFieldsValue({
account,
name,
organizationId: organization.id,
roleId,
});
};
// 用户角色多选框
const userRoleCheckbox = () =>
roleList.map(item => (
<Checkbox value={item.id}>
<a
onClick={e => {
e.preventDefault();
openRolePermissionsModal(item);
}}
>
{item.name}
</a>
</Checkbox>
));
// 选择门店多选框
const selectSupplierCheckbox = () => {
let list = supplierList;
const filterData = supplierList.filter(item => item.orgId === userInfo.orgId);
if (filterData.length) {
list = filterData;
}
return list.map(item => <Radio value={item.orgId}> {item.name}</Radio>);
};
// 表单验证辅助函数
const rulesHandler = (field, initialValue = '') => ({
rules: formRules[field] || [],
initialValue,
});
// 提交
const onSubmit = () => {
validateFields(async (err, fieldsValue) => {
console.log(err, fieldsValue);
if (err) {
return;
}
// 提交
console.log(fieldsValue);
const { organizationId, email } = fieldsValue;
const { orgId } = userInfo;
const code = UUID.createUUID();
const params = {
...fieldsValue,
code,
email: email || `${code}@stms.quantgroup.cn`,
organization: {
id: organizationId || orgId,
},
};
delete params.organizationId;
let api = addUser;
if (id) {
console.log(id, 222444);
params.id = id;
api = updateUser;
}
const res = await api(params);
if (res.code !== 2000) {
notification.warning({
message: res.detail || res.msg,
});
return;
}
notification.success({
message: '保存成功',
});
setTimeout(() => {
window.history.back();
}, 1000);
});
};
// 处理初始化密码自动填充函数
const handlePasswordChange = (e, fn) => {
if (e.target.value) {
fn('password');
} else {
fn('text');
}
};
const initData = async () => {
const roleListParams = {
page: 1,
size: 1000,
};
setLoading(true);
const roleListRes = await getRoleList(roleListParams);
const supplierListRes = await shopGetBySupplierId();
let accountDetailRes = null;
if (id) {
accountDetailRes = await getUserDetail({ id });
getAccountDetail(accountDetailRes);
}
setLoading(false);
getAllRoleList(roleListRes);
getAllSupplier(supplierListRes);
};
useEffect(() => {
initData();
if (id) {
setTitle('编辑用户');
}
}, []);
return (
<PageHeaderWrapper title={title}>
<div className={style['user-info']}>
<Spin spinning={loading}>
<Form className={style['user-info--form']} {...formLayout}>
<Form.Item label="用户名" extra="限32字符以内,限英文/数字/“@”“ .”">
{getFieldDecorator('account', rulesHandler('account'))(
<Input disabled={!!id} placeholder="请输入用户名" maxLength={32} />,
)}
</Form.Item>
<Form.Item label="姓名" extra="限10字符以内">
{getFieldDecorator('name', rulesHandler('name'))(
<Input maxLength={10} placeholder="请输入用户姓名" />,
)}
</Form.Item>
{id ? (
''
) : (
<>
<Form.Item label="初始密码" extra="限13-18字符,包含大小写字母、数字和特殊字符">
{getFieldDecorator('password', rulesHandler('password'))(
<Input
type={inputType}
onChange={e => handlePasswordChange(e, setInputType)}
placeholder="请设置登录密码"
/>,
)}
</Form.Item>
<Form.Item label="确认密码">
{getFieldDecorator('confirmPassword', rulesHandler('confirmPassword'))(
<Input
type={confirmInputType}
onChange={e => handlePasswordChange(e, setConfirmInputType)}
placeholder="请确认登录密码"
/>,
)}
</Form.Item>
</>
)}
<Form.Item label="选择门店" extra="仅限POP商家设置">
{getFieldDecorator('organizationId', rulesHandler('organizationId'))(
isPop && supplierList.length ? (
<Radio.Group disabled={!!id} style={{ width: '100%' }}>
{selectSupplierCheckbox()}
</Radio.Group>
) : (
<div>暂无门店信息</div>
),
)}
</Form.Item>
<Form.Item label="用户角色">
{getFieldDecorator('roleId', rulesHandler('roleId'))(
roleList.length ? (
<Checkbox.Group style={{ width: '100%' }}>{userRoleCheckbox()}</Checkbox.Group>
) : (
<div>暂无角色信息</div>
),
)}
</Form.Item>
<Form.Item {...btnLayout}>
<Button type="default" onClick={() => window.history.back()}>
返回
</Button>
<Button className={style['submit-button']} type="primary" onClick={onSubmit}>
提交
</Button>
</Form.Item>
</Form>
</Spin>
</div>
<RolePermissionsModal ref={rolePermissionsModalRef} />
</PageHeaderWrapper>
);
};
export default Form.create({})(AccountInfo);
.user-info {
padding: 30px 0;
background: #fff;
&--form {
width: 1200px;
}
.submit-button {
margin-left: 20px;
}
}
import React, { forwardRef, useImperativeHandle, useState, useRef, useEffect } from 'react';
import { Modal, Input, notification } from 'antd';
import { Form } from '@ant-design/compatible';
import { resetPassword } from '../../../service';
const FormComponent = props => {
const { record = {}, form } = props;
const { getFieldDecorator, setFieldsValue, getFieldValue } = form;
const [inputType, setInputType] = useState('text');
const [confirmInputType, setConfirmInputType] = useState('text');
const handlepassword = (rule, value, callback) => {
if (value && value !== getFieldValue('newPassword')) {
callback('两次输入不一致!');
}
// Note: 必须总是返回一个 callback,否则 validateFieldsAndScroll 无法响应
callback();
};
// 处理初始化密码自动填充函数
const handlePasswordChange = (e, fn) => {
if (e.target.value) {
fn('password');
} else {
fn('text');
}
};
const formLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 20 },
};
const formRules = {
newPassword: [
{ required: true, message: '请设置新密码' },
{
pattern: /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[\W_]).{13,18}$/g,
message: '密码格式错误',
},
],
password: [
{ required: true, message: '请确认新密码' },
{ validator: handlepassword, message: '两次密码不一致' },
],
};
const rulesHandler = name => ({
rules: formRules[name],
});
useEffect(() => {
setFieldsValue(record);
}, [record]);
return (
<Form {...formLayout}>
<Form.Item label="用户名">{record.name}</Form.Item>
<Form.Item label="新密码" extra="限13-18字符,包含大小写字母、数字和特殊字符">
{getFieldDecorator('newPassword', rulesHandler('newPassword'))(
<Input
type={inputType}
onChange={e => handlePasswordChange(e, setInputType)}
placeholder="请设置新密码"
/>,
)}
</Form.Item>
<Form.Item label="确认密码">
{getFieldDecorator('password', rulesHandler('password'))(
<Input
type={confirmInputType}
onChange={e => handlePasswordChange(e, setConfirmInputType)}
placeholder="请确认新密码"
/>,
)}
</Form.Item>
</Form>
);
};
const FormWarpper = Form.create({})(forwardRef(FormComponent));
const ResetPasswordModal = (props, ref) => {
const formRef = useRef();
const [visible, setVisible] = useState(false);
const [confirmLoading, setConfirmLoading] = useState(false);
const [record, setRecord] = useState({
name: '',
id: '',
});
const open = item => {
setVisible(true);
const { name, id } = item;
// 初始化数据
setRecord({
name,
id,
});
};
const onCancel = () => {
setVisible(false);
setConfirmLoading(false);
formRef.current.resetFields();
};
const onOk = () => {
formRef.current.validateFields(async (err, fieldsValue) => {
console.log('fieldsValue :>>', fieldsValue);
if (err) {
return;
}
setConfirmLoading(true);
const { password } = fieldsValue;
const params = {
id: record.id,
password,
};
const res = await resetPassword(params);
setConfirmLoading(false);
if (res.code !== 2000) {
notification.warning({
message: res.detail,
});
return;
}
notification.success({
message: '重置成功',
});
setConfirmLoading(false);
onCancel();
});
};
useImperativeHandle(ref, () => ({
open,
}));
const modalProps = {
title: '重置密码',
visible,
confirmLoading,
onCancel,
onOk,
};
return (
<Modal {...modalProps}>
<FormWarpper ref={formRef} record={record} />
</Modal>
);
};
export default forwardRef(ResetPasswordModal);
import React, { forwardRef, useImperativeHandle, useState } from 'react';
import { Modal } from 'antd';
import { RoleInfoComponent } from '../../../Role/RoleInfo';
const RolePermissionsModal = (props, ref) => {
const [visible, setVisible] = useState(false);
const [roleInfo, setRoleInfo] = useState({});
const open = record => {
setVisible(true);
console.log('record', record);
setRoleInfo(record);
};
const onCancel = () => {
setVisible(false);
};
useImperativeHandle(ref, () => ({
open,
}));
const modalProps = {
width: 600,
title: '查看角色',
visible,
footer: null,
onCancel,
};
const roleProps = {
id: roleInfo.id,
submittable: false,
readyonly: true,
height: '500px',
wrapperCol: {
span: 18,
},
};
console.log(roleProps);
return (
<>
{visible ? (
<Modal {...modalProps}>
<RoleInfoComponent {...roleProps} />
</Modal>
) : null}
</>
);
};
export default forwardRef(RolePermissionsModal);
import React, { forwardRef, useImperativeHandle, useState, useRef, useEffect } from 'react';
import { Modal, Select, notification } from 'antd';
import { Form } from '@ant-design/compatible';
import { userEnabled, userDisabled, userDelete } from '@/pages/systemManage/service';
const FormComponent = props => {
const { record = {}, form } = props;
const { getFieldDecorator, setFieldsValue } = form;
const formLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 20 },
};
const formRules = {
status: [{ required: true, message: '' }],
};
useEffect(() => {
setFieldsValue(record);
}, [record]);
const rulesHandler = name => ({
rules: formRules[name],
});
return (
<Form {...formLayout}>
<Form.Item label="用户名">{record.name}</Form.Item>
<Form.Item label="状态">
{getFieldDecorator('status', rulesHandler('status'))(
<Select>
<Select.Option value={2}>使用中</Select.Option>
<Select.Option value={3}>已禁用</Select.Option>
{record.currentStatus === 2 ? '' : <Select.Option value={1}>已删除</Select.Option>}
</Select>,
)}
</Form.Item>
</Form>
);
};
const FormWarpper = Form.create({})(forwardRef(FormComponent));
const UpdateStatusModal = (props, ref) => {
const { reload } = props;
const formRef = useRef();
const [visible, setVisible] = useState(false);
const [confirmLoading, setConfirmLoading] = useState(false);
const [record, setRecord] = useState({
name: '',
status: '',
id: '',
});
const open = item => {
setVisible(true);
const { name, status, id } = item;
// 初始化数据,currentStatus 用来判断状态选项
setRecord({
name,
status: status.value,
id,
currentStatus: status.value,
});
};
const onCancel = () => {
setVisible(false);
setConfirmLoading(false);
formRef.current.resetFields();
};
const onOk = () => {
formRef.current.validateFields(async (err, fieldsValue) => {
console.log('fieldsValue :>>', fieldsValue);
if (err) {
return;
}
const apiName = {
1: userDelete,
2: userEnabled,
3: userDisabled,
};
const params = {
id: record.id,
};
setConfirmLoading(true);
const res = await apiName[fieldsValue.status](params);
if (res.code !== 2000) {
notification.warning({
message: res.detail,
});
setConfirmLoading(false);
return;
}
setConfirmLoading(false);
notification.success({
message: '保存成功',
});
reload();
onCancel();
});
};
useImperativeHandle(ref, () => ({
open,
}));
const modalProps = {
title: '修改状态',
visible,
confirmLoading,
onCancel,
onOk,
};
return (
<Modal {...modalProps}>
<FormWarpper ref={formRef} record={record} />
</Modal>
);
};
export default forwardRef(UpdateStatusModal);
import React from 'react';
import { Divider } from 'antd';
export const getColumns = props => {
const {
toUserInfo,
openRolePermissionsModal,
openUpdateStatusModal,
openResetPasswordModal,
canEditable,
} = props;
return [
{
title: '用户名',
dataIndex: 'account',
},
{
title: '姓名',
dataIndex: 'name',
},
{
title: '创建时间',
dataIndex: 'createTime',
hideInSearch: true,
},
{
title: '最后一次登录时间',
dataIndex: 'lastLogin',
hideInSearch: true,
},
{
title: '角色',
dataIndex: 'creator',
render: (value, record) => {
const { roles } = record;
const roleElement = roles.map((role, index) => (
<>
<a onClick={() => openRolePermissionsModal(role)}>{role.name}</a>
{roles.length - 1 !== index ? '' : ''}
</>
));
return roleElement;
},
},
{
title: '状态',
dataIndex: 'status',
width: 150,
initialValue: '3',
hideInFilter: true,
valueEnum: {
all: { text: '全部', status: '' },
close: { text: '使用中', status: 2 },
running: { text: '已禁用', status: 3 },
},
render: value => {
const textMapping = {
2: '已使用',
3: '已禁用',
};
return textMapping[value.value] || '-';
},
},
{
title: '操作',
key: 'action',
width: 220,
hideInSearch: true,
render: (value, record) => {
if (!canEditable) {
return <>-</>;
}
return (
<>
<a
onClick={() => {
toUserInfo(record);
}}
>
编辑
</a>
<Divider type="vertical" />
<a
onClick={() => {
openUpdateStatusModal(record);
}}
>
修改状态
</a>
<Divider type="vertical" />
<a
onClick={() => {
openResetPasswordModal(record);
}}
>
重置密码
</a>
</>
);
},
},
];
};
import React, { useRef, useState, useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { Button, Divider } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table';
import { connect } from 'umi';
// data
import { ACCOUNT_MANAGE } from '@/../config/permission.config';
import { getColumns } from './data';
// compoents
import RolePermissionsModal from './components/RolePermissionsModal';
import UpdateStatusModal from './components/UpdateStatusModal';
import ResetPasswordModal from './components/ResetPasswordModal';
// mock
import { getUserList } from '../service';
const Account = props => {
const { permissions } = props;
const history = useHistory();
const actionRef = useRef();
const formRef = useRef();
const rolePermissionsModalRef = useRef();
const updateStatusModalRef = useRef();
const resetPasswordModal = useRef();
// 权限控制-新增/修改
const canEditable = permissions[ACCOUNT_MANAGE.EDITABLE];
// 获取当前用户组织信息
const userInfo = JSON.parse(localStorage.getItem('user') || '{}');
// 临时缓存当前账户的角色id
const setSelectedRoleIds = roleIds => {
window.sessionStorage.setItem('_selectedRoleIds', JSON.stringify(roleIds));
};
// 清空临时缓存的角色id
const clearnSelectedRoleIds = () => {
window.sessionStorage.removeItem('_selectedRoleIds');
};
// 新增编辑
const toUserInfo = ({ id, roles = [] } = {}) => {
const query = id ? { id } : {};
if (id) {
const roleIds = roles.map(role => role.id);
setSelectedRoleIds(roleIds);
}
history.push({
pathname: '/systemManage/account/userInfo',
query,
});
};
// 角色权限 modal
const openRolePermissionsModal = record => {
rolePermissionsModalRef.current.open(record);
};
// 修改状态 modal
const openUpdateStatusModal = record => {
updateStatusModalRef.current.open(record);
};
// 重置密码 modal
const openResetPasswordModal = record => {
resetPasswordModal.current.open(record);
};
const reload = () => {
actionRef.current.reload();
};
// 获取列表配置
const columns = getColumns({
toUserInfo,
openRolePermissionsModal,
openUpdateStatusModal,
openResetPasswordModal,
canEditable,
});
// 表格属性
const tableProps = {
columns,
rowKey: 'id',
request: async params => {
console.log('搜索', params);
const { current: page, pageSize: size } = params;
const res = await getUserList({
page,
size,
id: userInfo,
});
const { content = [], totalElements } = res.data;
return {
data: content,
success: true,
total: totalElements,
};
},
toolBarRender: () => {
// TODO: 权限控制
if (canEditable) {
return [
<Button type="primary" onClick={() => toUserInfo()}>
新增用户
</Button>,
];
}
return [];
},
};
// 搜索属性
const searchProps = {
collapsed: false,
collapseRender: () => null,
};
useEffect(() => {
clearnSelectedRoleIds();
}, []);
return (
<PageHeaderWrapper>
<ProTable actionRef={actionRef} formRef={formRef} {...tableProps} search={false}></ProTable>
<RolePermissionsModal ref={rolePermissionsModalRef} />
<UpdateStatusModal reload={reload} ref={updateStatusModalRef} />
<ResetPasswordModal reload={reload} ref={resetPasswordModal} />
</PageHeaderWrapper>
);
};
export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(Account);
import React, { useRef } from 'react';
import { useHistory } from 'react-router-dom';
import { Button, Divider } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table';
// mock
import { logList } from '../mock/log';
const columns = [
{
title: '操作人',
dataIndex: 'name',
},
{
title: '一级菜单',
dataIndex: 'menu',
},
{
title: '二级菜单',
dataIndex: 'subMenu',
},
{
title: '操作点',
dataIndex: 'status',
hideInSearch: true,
},
{
title: '操作时间',
hideInSearch: true,
dataIndex: 'actionTime',
},
{
title: '操作时间2',
hideInTable: true,
dataIndex: 'actionTime1',
valueType: 'dateRange',
},
{
title: '操作',
key: 'action',
hideInSearch: true,
render: () => (
<>
<a>查看</a>
</>
),
},
];
const SystemLog = props => {
const history = useHistory();
const actionRef = useRef();
const formRef = useRef();
const toUserInfo = (record = {}) => {
const { id } = record;
history.push({
pathname: '/SystemManage/Account/UserInfo',
query: {
id: 1,
},
});
};
// 表格属性
const tableProps = {
columns,
rowKey: 'id',
request: params => {
console.log('搜索', params);
return new Promise(resolve => {
setTimeout(() => {
resolve({
data: logList,
success: true,
});
}, 2000);
});
},
search: {
collapsed: false,
collapseRender: () => null,
},
};
// 搜索属性
const searchProps = {};
return (
<PageHeaderWrapper>
<ProTable actionRef={actionRef} formRef={formRef} {...tableProps}></ProTable>
</PageHeaderWrapper>
);
};
export default SystemLog;
import React, { forwardRef, useImperativeHandle, useState, useEffect } from 'react';
import { Input, Checkbox, Button, Tree, notification, Spin } from 'antd';
import { Form } from '@ant-design/compatible';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import { getUserPermissions } from '@/services/user';
import { addResource, getRoleDetail, modifyRole } from '../../service';
import UUID from '@/utils/uuid';
import style from './index.less';
import { APP_CODE, TENANT_ID } from '@/utils/constants';
// mock
const { TextArea } = Input;
const { TreeNode } = Tree;
/**
* 权限表单/权限展示
* @param {*} props
* @param {boolean} props.submittable 是否可提交(即:是否展示操作)
* @param {number} props.id 判断是否是新增
* @param {boolean} props.readyonly 是否全部为只读(查看操作)
*/
const RoleInfo = props => {
const {
id,
submittable = true,
readyonly = false,
defaultExpandAll = true,
height,
labelCol = { span: 4 },
wrapperCol = { span: 12 },
} = props;
const { getFieldDecorator, getFieldValue, validateFields, setFieldsValue } = props.form;
// 可选的权限数据
const [permissionsData, setPermissionsData] = useState([]);
// 当前选中的权限-仅提交时使用
const [selectedPermissions, setSelectedPermissions] = useState([]);
const [detailInfo, setDetailInfo] = useState({});
const [loading, setLoading] = useState(false);
// 表单布局
const formLayout = {
labelCol,
wrapperCol,
};
const btnLayout = {
wrapperCol: { offset: 4, span: 12 },
};
// 表单验证
const formRules = {
name: [{ required: true, message: '请设置角色名称' }],
description: [{ required: true, message: '请填写角色描述' }],
selected: [{ type: 'array', required: true, message: '请选择权限' }],
};
const treeProps = {
defaultExpandAll,
};
// 表单验证辅助函数
const rulesHandler = field => ({
rules: formRules[field] || [],
});
// 提交数据
const onSubmit = () => {
validateFields(async (err, fieldsValue) => {
console.log('fieldsValue :>>', fieldsValue);
if (err) {
return;
}
// 提交
const params = {
tenantId: TENANT_ID,
code: UUID.createUUID(),
app: {
appCode: APP_CODE,
selected: selectedPermissions,
},
...fieldsValue,
};
if (id) {
params.id = id;
}
// 删除提交时无用的字段
delete params.selected;
console.log('params :>>', params);
const res = await addResource(params);
console.log(res);
if (res.code !== 2000) {
notification.warning({
message: `${res.msg}:${res.detail}`,
});
return;
}
notification.success({
message: '提交成功',
});
setTimeout(() => {
window.history.back();
}, 1000);
});
};
// 选择权限回调
const onPermissionsCheck = checkedKeys => {
if (readyonly) {
return;
}
setSelectedPermissions(checkedKeys);
setFieldsValue({
selected: checkedKeys,
});
};
// 初始化权限数据
// TODO:分离接口
const initPermissions = (res, roleId) => {
if (res.code !== 2000) {
notification.warning({
message: res.msg,
});
}
let resource = [];
let selected = [];
if (roleId) {
const { resource: resourceData, selected: selectedData } = res.data;
resource = resourceData;
selected = selectedData;
} else {
resource = res.data;
}
setPermissionsData(resource);
setSelectedPermissions(selected);
setFieldsValue({
selected,
});
};
// 初始化当前角色数据
const initRoleData = res => {
if (res.code !== 2000) {
notification.warning({ message: res.detail });
return;
}
console.log(res.data);
const { name, description } = res.data;
setFieldsValue({
name,
description,
});
setDetailInfo({
name,
description,
});
};
const initData = async () => {
const roleId = id || null;
setLoading(true);
const permissionsRes = await getUserPermissions(roleId);
if (id) {
const roleDetailRes = await getRoleDetail({ id });
initRoleData(roleDetailRes);
}
setLoading(false);
initPermissions(permissionsRes, roleId);
};
useEffect(() => {
initData();
}, []);
const renderTreeNodes = data =>
data.map(item => {
if (item.childNodes) {
return (
<TreeNode title={item.node.name} key={item.node.id} dataRef={item}>
{renderTreeNodes(item.childNodes)}
</TreeNode>
);
}
return <TreeNode key={item.node.id} {...item} />;
});
return (
<div className={style['info-box']}>
<Spin spinning={loading}>
<Form className={style['info-box--form']} {...formLayout}>
<Form.Item label="角色名称">
{readyonly
? detailInfo.name
: getFieldDecorator('name', rulesHandler('name'))(
<Input maxLength={10} placeholder="10个字以内" />,
)}
</Form.Item>
<Form.Item label="角色描述">
{readyonly
? detailInfo.description || '-'
: getFieldDecorator('description', rulesHandler('description'))(
<TextArea maxLength={30} placeholder="30个字以内"></TextArea>,
)}
</Form.Item>
<Form.Item label="权限">
{getFieldDecorator('selected', rulesHandler('selected'))(
<div className={style.tree} style={{ height }}>
{permissionsData.length ? (
<Tree
checkable
selectable={false}
defaultExpandAll
onCheck={onPermissionsCheck}
checkedKeys={selectedPermissions}
>
{renderTreeNodes(permissionsData)}
</Tree>
) : (
''
)}
</div>,
)}
</Form.Item>
{submittable ? (
<Form.Item {...btnLayout}>
<Button type="default" onClick={() => window.history.back()}>
返回
</Button>
<Button className={style['submit-button']} type="primary" onClick={onSubmit}>
提交
</Button>
</Form.Item>
) : (
''
)}
</Form>
</Spin>
</div>
);
};
export const RoleInfoComponent = Form.create({})(RoleInfo);
const PageWapperComponent = props => {
const { id } = props.location?.query;
const [title, setTitle] = useState('新增角色');
useEffect(() => {
if (id) {
setTitle('编辑角色');
}
}, []);
const roleInfo = {
id,
};
return (
<PageHeaderWrapper title={title}>
<RoleInfoComponent {...roleInfo} />
</PageHeaderWrapper>
);
};
export default PageWapperComponent;
.info-box {
padding: 30px 0;
background: #fff;
&--form {
max-width: 1200px;
}
.submit-button {
margin-left: 20px;
}
}
.tree {
min-height: 500px;
padding: 20px 30px;
overflow: auto;
border: 1px solid #efefef;
}
import React from 'react';
import { Divider, Popconfirm } from 'antd';
export const getColumns = props => {
const { onDeleteRole, toRoleInfo, canEditable } = props;
return [
{
title: '角色ID',
dataIndex: 'id',
hideInTable: true,
},
{
title: '角色名称',
dataIndex: 'name',
},
{
title: '角色描述',
dataIndex: 'description',
hideInSearch: true,
},
{
title: '状态',
dataIndex: 'status',
hideInSearch: true,
render: value => value.name,
},
{
title: '关联账号',
dataIndex: 'userCount',
hideInSearch: true,
},
{
title: '创建人',
dataIndex: 'creator',
hideInSearch: true,
},
{
title: '创建日期',
hideInSearch: true,
dataIndex: 'createTime',
},
{
title: '操作',
key: 'action',
hideInSearch: true,
render: (value, record) => {
if (!canEditable) {
return '-';
}
return (
<>
<a onClick={() => toRoleInfo(record)}>编辑</a>
{record.userCount === 0 ? (
<>
<Divider type="vertical" />
<Popconfirm
placement="top"
title="确定删除该角色吗?"
onConfirm={() => onDeleteRole(record)}
okText="确定"
cancelText="取消"
>
<a>删除</a>
</Popconfirm>
</>
) : (
''
)}
</>
);
},
},
];
};
import React, { useRef } from 'react';
import { useHistory } from 'react-router-dom';
import { Button, notification } from 'antd';
import { PageHeaderWrapper } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table';
import { connect } from 'umi';
import { ROLE_MANAGE } from '@/../config/permission.config';
import { deleteRole, getRoleList } from '../service';
// data
import { getColumns } from './data';
const Role = props => {
const { permissions } = props;
const actionRef = useRef();
const formRef = useRef();
const history = useHistory();
// 权限控制
const canEditable = permissions[ROLE_MANAGE.EDITABLE];
const toRoleInfo = ({ id = null } = {}) => {
const query = id ? { id } : {};
history.push({
pathname: '/systemManage/role/roleInfo',
query,
});
};
// 删除
const onDeleteRole = async ({ id }) => {
const res = await deleteRole({ id });
if (res.code !== 2000) {
notification.warning({
message: res.detail,
});
return;
}
notification.success({
message: '删除成功',
});
};
const columns = getColumns({
onDeleteRole,
toRoleInfo,
canEditable,
});
// 表格属性
const tableProps = {
columns,
rowKey: 'id',
request: async params => {
console.log('搜索:', params);
const { current: page, pageSize: size } = params;
const res = await getRoleList({ page, size, ...params });
const { content, totalElements } = res.data;
return {
success: true,
data: content,
total: totalElements,
};
},
toolBarRender: () => [
canEditable ? (
<Button type="primary" onClick={() => toRoleInfo()}>
新增角色
</Button>
) : (
<></>
),
],
};
// 搜索属性
const searchProps = {
collapsed: false,
collapseRender: () => null,
};
return (
<PageHeaderWrapper>
<ProTable actionRef={actionRef} formRef={formRef} {...tableProps} search={false}></ProTable>
</PageHeaderWrapper>
);
};
export default connect(({ menu }) => ({
permissions: menu.permissions,
}))(Role);
export const logList = [
{
id: 1,
name: 'liteng',
actionTime: '2017-01-01',
menu: '系统管理',
subMenu: '账号管理',
status: '编辑',
},
];
export const roleList = [
{
id: 1,
username: 'liteng',
name: '李腾',
createAt: '2017-01-01',
lastAt: '2020-01-01',
role: '超级管理员',
status: '启用',
},
];
export const treeData = [
{
title: '0-0',
key: '0-0',
children: [
{
title: '0-0-0',
key: '0-0-0',
children: [
{ title: '0-0-0-0', key: '0-0-0-0' },
{ title: '0-0-0-1', key: '0-0-0-1' },
{ title: '0-0-0-2', key: '0-0-0-2' },
],
},
{
title: '0-0-1',
key: '0-0-1',
children: [
{ title: '0-0-1-0', key: '0-0-1-0' },
{ title: '0-0-1-1', key: '0-0-1-1' },
{ title: '0-0-1-2', key: '0-0-1-2' },
],
},
{
title: '0-0-2',
key: '0-0-2',
},
],
},
{
title: '0-1',
key: '0-1',
children: [
{ title: '0-1-0-0', key: '0-1-0-0' },
{ title: '0-1-0-1', key: '0-1-0-1' },
{ title: '0-1-0-2', key: '0-1-0-2' },
],
},
{
title: '0-2',
key: '0-2',
},
];
import _ from 'lodash';
import request from '@/utils/request';
import { APP_CODE } from '@/utils/constants';
const PAGE = 1;
const SIZE = 20;
/**
* @name 子账号列表
* @param {Object} params
* @see http://yapi.quantgroups.com/project/509/interface/api/42832
*/
export function getUserList({ page = PAGE, size = SIZE }) {
return request.post(`/v2/user/list/${page}/${size}`, {
data: {},
});
}
/**
* @name 子账号详情
* @param {Object} params
* @param {number} params.id 子账号id
* @see http://yapi.quantgroups.com/project/509/interface/api/42856
*/
export function getUserDetail({ id }) {
return request.get(`/v2/user/info/${id}`);
}
/**
* @name 新增/修改子账号
* @see http://yapi.quantgroups.com/project/509/interface/api/42896
*/
export function addUser(params) {
return request.post('/v2/user/addnew', {
data: params,
});
}
/**
* @name 修改子账号
* @see http://yapi.quantgroups.com/project/509/interface/api/43344
*/
export function updateUser(params) {
return request.post('/v2/user/update', {
data: params,
});
}
/**
* @name 用户禁用
* @param {Object} params
* @param {number} params.id
* @see http://yapi.quantgroups.com/project/509/interface/api/42864
*/
export function userDisabled({ id }) {
return request.post(`/v2/user/disabled/${id}`);
}
/**
* @name 用户启用
* @param {Object} params
* @param {number} params.id
* @see http://yapi.quantgroups.com/project/509/interface/api/42880
*/
export function userEnabled({ id }) {
return request.post(`/v2/user/enabled/${id}`);
}
/**
* @name 删除用户
* @param {Object} params
* @param {number} params.id
* @see http://yapi.quantgroups.com/project/509/interface/api/43120
*/
export function userDelete({ id }) {
return request.post(`/v2/user/delete/${id}`);
}
/**
* @name 重置/修改密码
* @param {Object} params
* @param {string} params.password 确认密码
* @see http://yapi.quantgroups.com/project/509/interface/api/43128
*/
export function resetPassword(params) {
return request.post('/v2/user/password/resetpassword', {
data: params,
});
}
/**
* @name 角色列表-分页
* @param {Object} params
* @see http://yapi.quantgroups.com/project/509/interface/api/41816
*/
export function getRoleList({ page, size }) {
return request.post(`/v2/role/list/${page}/${size}?appCode=${APP_CODE}`, {
data: {},
});
}
/**
* @name 角色详情
* @param {Object} params
* @param {number} params.id 角色id
* @see http://yapi.quantgroups.com/project/509/interface/api/41848
*
*/
export async function getRoleDetail({ id }) {
return request.get(`/v2/role/info/${id}`);
}
/**
* @name 新增角色
* @param {Object} params
* @see http://yapi.quantgroups.com/project/509/interface/api/42920
*/
export async function addResource(params) {
return request.post('/v2/role/addResource', {
data: params,
});
}
/**
* @name 修改角色
* @param {Object} params
* @see http://yapi.quantgroups.com/project/509/interface/api/42928
*/
export async function modifyRole(params) {
return request.post('/v2/role/updateResource', params);
}
/**
* @name 删除角色
* @param {Object} params
* @param {number} params.id 角色id
* @see http://yapi.quantgroups.com/project/509/interface/api/41832
*/
export async function deleteRole({ id }) {
return request.post(`/v2/role/delete/${id}`);
}
import request from '@/utils/request'; import request from '@/utils/request';
import { APP_CODE } from '@/utils/constants';
export async function getMenuData() { export async function getMenuData() {
return request.post('/v2/resource/APP013'); return request.post(`/v2/resource/${APP_CODE}`);
} }
import { APP_CODE } from '@/utils/constants';
import request from '@/utils/request'; import request from '@/utils/request';
export async function queryCurrent() { export async function queryCurrent() {
...@@ -9,3 +10,10 @@ export async function homeInfo() { ...@@ -9,3 +10,10 @@ export async function homeInfo() {
// 查询主页信息 // 查询主页信息
return request.post('/home/info'); return request.post('/home/info');
} }
export function getUserPermissions(roleId) {
if (roleId) {
return request.post(`/v2/resource/${APP_CODE}/${roleId}`);
}
return request.post(`/v2/resource/${APP_CODE}`);
}
export const APP_CODE = 'APP013';
export const TENANT_ID = 560761;
// 小程序权限标识符, 用于过滤掉返回的小程序权限数据
export const APPLETS_PERMISSION_IDENTIFIER = 'applets';
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment