|
@@ -0,0 +1,345 @@
|
|
|
+import React, { useCallback, useEffect, useState, memo, useRef } from 'react';
|
|
|
+
|
|
|
+import { PageContainer } from '@ant-design/pro-layout';
|
|
|
+
|
|
|
+import { Card, Row, Col, Table, Button, message, Space, Tag, Image, Popconfirm } from 'antd';
|
|
|
+
|
|
|
+import { ConnectState } from '@/models/connect';
|
|
|
+
|
|
|
+import { connect, Dispatch } from 'umi';
|
|
|
+
|
|
|
+import { IBanner } from './types';
|
|
|
+
|
|
|
+import { Role } from '@/models/user';
|
|
|
+
|
|
|
+import { getBanner, deleteBanner, opraBanner } from '@/services/notice';
|
|
|
+
|
|
|
+import { DndProvider, useDrag, useDrop } from 'react-dnd';
|
|
|
+
|
|
|
+import { HTML5Backend } from 'react-dnd-html5-backend';
|
|
|
+
|
|
|
+import update from 'immutability-helper';
|
|
|
+
|
|
|
+import BannerDrawer from './modal';
|
|
|
+
|
|
|
+import SwiperModal from './swiper';
|
|
|
+
|
|
|
+import './common.less';
|
|
|
+
|
|
|
+const type = 'DraggableBodyRow';
|
|
|
+
|
|
|
+/**@ts-ignore */
|
|
|
+
|
|
|
+const DraggableBodyRow = ({ index, moveRow, className, style, ...restProps }) => {
|
|
|
+ const ref = useRef();
|
|
|
+ const [{ isOver, dropClassName }, drop] = useDrop({
|
|
|
+ accept: type,
|
|
|
+ collect: (monitor) => {
|
|
|
+ const { index: dragIndex } = monitor.getItem() || {};
|
|
|
+ if (dragIndex === index) {
|
|
|
+ return {};
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ isOver: monitor.isOver(),
|
|
|
+ dropClassName: dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
|
|
|
+ };
|
|
|
+ },
|
|
|
+ drop: (item) => {
|
|
|
+ moveRow(item.index, index);
|
|
|
+ },
|
|
|
+ });
|
|
|
+ const [, drag] = useDrag({
|
|
|
+ type,
|
|
|
+ item: { index },
|
|
|
+ collect: (monitor) => ({
|
|
|
+ isDragging: monitor.isDragging(),
|
|
|
+ }),
|
|
|
+ });
|
|
|
+ drop(drag(ref));
|
|
|
+
|
|
|
+ return (
|
|
|
+ <tr
|
|
|
+ ref={ref}
|
|
|
+ className={`${className}${isOver ? dropClassName : ''}`}
|
|
|
+ style={{ cursor: 'move', ...style }}
|
|
|
+ {...restProps}
|
|
|
+ />
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+interface IProps {
|
|
|
+ dispatch: Dispatch;
|
|
|
+ roleList: Role[];
|
|
|
+}
|
|
|
+
|
|
|
+interface IState {
|
|
|
+ roleId: string;
|
|
|
+ visible: boolean;
|
|
|
+ bannerList: IBanner[];
|
|
|
+ loading: boolean;
|
|
|
+ modalVisible: boolean;
|
|
|
+}
|
|
|
+
|
|
|
+const MemoBannerDrawer = memo(BannerDrawer);
|
|
|
+
|
|
|
+const MemoSwiperModal = memo(SwiperModal);
|
|
|
+
|
|
|
+const Banner: React.FC<IProps> = ({ roleList, dispatch }) => {
|
|
|
+ const [state, setState] = useState<IState>({
|
|
|
+ roleId: '',
|
|
|
+ visible: false,
|
|
|
+ modalVisible: false,
|
|
|
+ loading: false,
|
|
|
+ bannerList: [],
|
|
|
+ });
|
|
|
+
|
|
|
+ const { roleId, visible, bannerList, loading, modalVisible } = state;
|
|
|
+
|
|
|
+ // 请求身份分类
|
|
|
+ useEffect(() => {
|
|
|
+ dispatch({
|
|
|
+ type: 'user/getRoleList',
|
|
|
+ payload: {
|
|
|
+ curPage: 1,
|
|
|
+ passSize: 100,
|
|
|
+ },
|
|
|
+ });
|
|
|
+ }, []);
|
|
|
+
|
|
|
+ // 设置默认的roleId
|
|
|
+ useEffect(() => {
|
|
|
+ if (roleList.length === 0) return;
|
|
|
+
|
|
|
+ setState({
|
|
|
+ ...state,
|
|
|
+ roleId: roleList[0].id,
|
|
|
+ });
|
|
|
+ }, [roleList]);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ if (!roleId) return;
|
|
|
+ GetBanner();
|
|
|
+ }, [roleId]);
|
|
|
+
|
|
|
+ // 打开或者关闭新增轮播图面板
|
|
|
+ const opraModal = (_state: boolean, reloadTable = false) => {
|
|
|
+ console.log(_state, '_state');
|
|
|
+
|
|
|
+ setState({
|
|
|
+ ...state,
|
|
|
+ visible: _state,
|
|
|
+ });
|
|
|
+
|
|
|
+ if (reloadTable) {
|
|
|
+ GetBanner();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 查询banner
|
|
|
+ const GetBanner = async () => {
|
|
|
+ setState({
|
|
|
+ ...state,
|
|
|
+ visible: false,
|
|
|
+ loading: true,
|
|
|
+ });
|
|
|
+ const { status, data } = await getBanner(roleId);
|
|
|
+ console.log(status, data);
|
|
|
+ if (status === 200) {
|
|
|
+ setState({
|
|
|
+ ...state,
|
|
|
+ visible: false,
|
|
|
+ loading: false,
|
|
|
+ bannerList: data.map((item: IBanner, index: number) => {
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ sort: index + 1,
|
|
|
+ };
|
|
|
+ }),
|
|
|
+ });
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 删除banner
|
|
|
+ const DeleteBanner = async (id: string) => {
|
|
|
+ const { status, data } = await deleteBanner(id);
|
|
|
+ console.log(status, data);
|
|
|
+ if (status === 200 && data) {
|
|
|
+ GetBanner();
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 对banner进行添加或者修改
|
|
|
+ const OpraBanner = async (_bannerList: IBanner[]) => {
|
|
|
+ const { status, data } = await opraBanner(_bannerList, roleId);
|
|
|
+
|
|
|
+ if (status === 200 && data) {
|
|
|
+ message.success('轮播顺序已调整');
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 打开预览弹窗
|
|
|
+ const opraPreviewModal = (_visible: boolean) => {
|
|
|
+ setState({
|
|
|
+ ...state,
|
|
|
+ modalVisible: _visible,
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ const columns = [
|
|
|
+ {
|
|
|
+ title: '封面',
|
|
|
+ dataIndex: 'imgUrl',
|
|
|
+ key: 'imgUrl',
|
|
|
+ render: (text: any, record: IBanner) => (
|
|
|
+ <Image
|
|
|
+ src={record.imgUrl}
|
|
|
+ width={150}
|
|
|
+ height={80}
|
|
|
+ alt="我炸裂了"
|
|
|
+ style={{ objectFit: 'cover' }}
|
|
|
+ />
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '创建时间',
|
|
|
+ dataIndex: 'createTime',
|
|
|
+ key: 'createTime',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '轮播顺序',
|
|
|
+ dataIndex: 'sort',
|
|
|
+ key: 'sort',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '创建人',
|
|
|
+ dataIndex: 'username',
|
|
|
+ key: 'username',
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '是否启用',
|
|
|
+ dataIndex: 'isShow',
|
|
|
+ key: 'isShow',
|
|
|
+ render: (text: any, record: IBanner) => (
|
|
|
+ <Tag color={record.isShow ? 'blue' : 'warning'}>{record.isShow ? '启用' : '禁用'}</Tag>
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ dataIndex: 'action',
|
|
|
+ key: 'action',
|
|
|
+ render: (text: any, record: IBanner) => (
|
|
|
+ <>
|
|
|
+ <Space>
|
|
|
+ <a onClick={() => opraModal(true)}>查看</a>{' '}
|
|
|
+ </Space>
|
|
|
+ <Space>
|
|
|
+ <Popconfirm title="确定要删除这张轮播图吗" onConfirm={() => DeleteBanner(record.id)}>
|
|
|
+ <a>删除</a>
|
|
|
+ </Popconfirm>
|
|
|
+ </Space>
|
|
|
+ </>
|
|
|
+ ),
|
|
|
+ },
|
|
|
+ ];
|
|
|
+
|
|
|
+ const components = {
|
|
|
+ body: {
|
|
|
+ row: DraggableBodyRow,
|
|
|
+ },
|
|
|
+ };
|
|
|
+
|
|
|
+ const moveRow = useCallback(
|
|
|
+ (dragIndex, hoverIndex) => {
|
|
|
+ const dragRow = bannerList[dragIndex];
|
|
|
+ console.log(dragRow, 'dragRowdragRow');
|
|
|
+ const r = update(bannerList, {
|
|
|
+ $splice: [
|
|
|
+ [dragIndex, 1],
|
|
|
+ [hoverIndex, 0, dragRow],
|
|
|
+ ],
|
|
|
+ });
|
|
|
+
|
|
|
+ const $par = r.map((_banner, index) => {
|
|
|
+ return {
|
|
|
+ ..._banner,
|
|
|
+ sort: index + 1,
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ console.log(r, '我是r');
|
|
|
+ OpraBanner($par);
|
|
|
+ setState({
|
|
|
+ ...state,
|
|
|
+ bannerList: $par,
|
|
|
+ });
|
|
|
+ },
|
|
|
+ [bannerList],
|
|
|
+ );
|
|
|
+
|
|
|
+ return (
|
|
|
+ <PageContainer
|
|
|
+ title="轮播图管理"
|
|
|
+ tabActiveKey={roleId}
|
|
|
+ tabList={roleList.map((role) => {
|
|
|
+ return {
|
|
|
+ key: role.id,
|
|
|
+ tab: role.label,
|
|
|
+ };
|
|
|
+ })}
|
|
|
+ onTabChange={(activeKey) => {
|
|
|
+ setState({ ...state, roleId: activeKey });
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <Card
|
|
|
+ extra={
|
|
|
+ <Row gutter={6}>
|
|
|
+ <Col>
|
|
|
+ {' '}
|
|
|
+ <Button type="primary" onClick={() => opraPreviewModal(true)}>
|
|
|
+ 预览
|
|
|
+ </Button>
|
|
|
+ </Col>
|
|
|
+ <Col>
|
|
|
+ {' '}
|
|
|
+ <Button type="primary" onClick={() => opraModal(true)}>
|
|
|
+ 新增轮播图
|
|
|
+ </Button>
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
+ }
|
|
|
+ >
|
|
|
+ <DndProvider backend={HTML5Backend}>
|
|
|
+ <Table
|
|
|
+ loading={loading}
|
|
|
+ dataSource={bannerList}
|
|
|
+ columns={columns}
|
|
|
+ components={components}
|
|
|
+ onRow={(record, index) => ({
|
|
|
+ index,
|
|
|
+ moveRow,
|
|
|
+ })}
|
|
|
+ />
|
|
|
+ </DndProvider>
|
|
|
+ </Card>
|
|
|
+
|
|
|
+ {/* 弹出层 */}
|
|
|
+ <MemoBannerDrawer
|
|
|
+ visible={visible}
|
|
|
+ opraModal={opraModal}
|
|
|
+ roleData={roleList.filter((role) => role.id === roleId)[0]}
|
|
|
+ />
|
|
|
+
|
|
|
+ <div style={{ position: 'fixed', left: '50%', top: '50%', zIndex: 10000, color: '#fff' }}>
|
|
|
+ <MemoSwiperModal
|
|
|
+ visible={modalVisible}
|
|
|
+ bannerList={bannerList}
|
|
|
+ opraPreviewModal={opraPreviewModal}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </PageContainer>
|
|
|
+ );
|
|
|
+};
|
|
|
+
|
|
|
+export default connect(({ user }: ConnectState) => ({
|
|
|
+ roleList: user.roleList,
|
|
|
+}))(Banner);
|