|
|
|
@ -1,246 +1,207 @@
|
|
|
|
|
import type { FC } from 'react';
|
|
|
|
|
import React, { useState } from 'react';
|
|
|
|
|
import { DownOutlined, PlusOutlined } from '@ant-design/icons';
|
|
|
|
|
import {
|
|
|
|
|
Avatar,
|
|
|
|
|
Button,
|
|
|
|
|
Card,
|
|
|
|
|
Col,
|
|
|
|
|
Dropdown,
|
|
|
|
|
Input,
|
|
|
|
|
List,
|
|
|
|
|
Menu,
|
|
|
|
|
Modal,
|
|
|
|
|
Progress,
|
|
|
|
|
Radio,
|
|
|
|
|
Row,
|
|
|
|
|
} from 'antd';
|
|
|
|
|
|
|
|
|
|
/** 资质考试 */
|
|
|
|
|
//import { AlignLeftOutlined, PlusOutlined } from '@ant-design/icons';
|
|
|
|
|
import { Switch, Button, Card, Col, List, Menu, Progress, Row, Typography, Space, Divider, Radio, Checkbox, Tag, Dropdown } from 'antd';
|
|
|
|
|
import { PageContainer } from '@ant-design/pro-layout';
|
|
|
|
|
import { useRequest } from 'umi';
|
|
|
|
|
import moment from 'moment';
|
|
|
|
|
import OperationModal from './components/OperationModal';
|
|
|
|
|
import { addFakeList, queryFakeList, removeFakeList, updateFakeList } from './service';
|
|
|
|
|
import type { BasicListItemDataType } from './data.d';
|
|
|
|
|
//import { useRequest } from 'umi';
|
|
|
|
|
//import { queryFakeList } from './service';
|
|
|
|
|
//import type { CardListItemDataType } from './data';
|
|
|
|
|
import styles from './style.less';
|
|
|
|
|
|
|
|
|
|
const RadioButton = Radio.Button;
|
|
|
|
|
const RadioGroup = Radio.Group;
|
|
|
|
|
const { Search } = Input;
|
|
|
|
|
|
|
|
|
|
const Info: FC<{
|
|
|
|
|
title: React.ReactNode;
|
|
|
|
|
value: React.ReactNode;
|
|
|
|
|
bordered?: boolean;
|
|
|
|
|
}> = ({ title, value, bordered }) => (
|
|
|
|
|
<div className={styles.headerInfo}>
|
|
|
|
|
<span>{title}</span>
|
|
|
|
|
<p>{value}</p>
|
|
|
|
|
{bordered && <em />}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const ListContent = ({
|
|
|
|
|
data: { owner, createdAt, percent, status },
|
|
|
|
|
}: {
|
|
|
|
|
data: BasicListItemDataType;
|
|
|
|
|
}) => (
|
|
|
|
|
<div className={styles.listContent}>
|
|
|
|
|
<div className={styles.listContentItem}>
|
|
|
|
|
<span>Owner</span>
|
|
|
|
|
<p>{owner}</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles.listContentItem}>
|
|
|
|
|
<span>开始时间</span>
|
|
|
|
|
<p>{moment(createdAt).format('YYYY-MM-DD HH:mm')}</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div className={styles.listContentItem}>
|
|
|
|
|
<Progress percent={percent} status={status} strokeWidth={6} style={{ width: 180 }} />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
export const BasicList: FC = () => {
|
|
|
|
|
const [done, setDone] = useState<boolean>(false);
|
|
|
|
|
const [visible, setVisible] = useState<boolean>(false);
|
|
|
|
|
const [current, setCurrent] = useState<Partial<BasicListItemDataType> | undefined>(undefined);
|
|
|
|
|
|
|
|
|
|
const {
|
|
|
|
|
data: listData,
|
|
|
|
|
loading,
|
|
|
|
|
mutate,
|
|
|
|
|
} = useRequest(() => {
|
|
|
|
|
return queryFakeList({
|
|
|
|
|
count: 50,
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
const { run: postRun } = useRequest(
|
|
|
|
|
(method, params) => {
|
|
|
|
|
if (method === 'remove') {
|
|
|
|
|
return removeFakeList(params);
|
|
|
|
|
}
|
|
|
|
|
if (method === 'update') {
|
|
|
|
|
return updateFakeList(params);
|
|
|
|
|
}
|
|
|
|
|
return addFakeList(params);
|
|
|
|
|
//import SubMenu from 'antd/lib/menu/SubMenu';
|
|
|
|
|
//import ProCard from '@ant-design/pro-card';
|
|
|
|
|
import ProList from '@ant-design/pro-list';
|
|
|
|
|
import { ReactText, useState } from 'react';
|
|
|
|
|
import { PlusOutlined, DeleteOutlined, DownloadOutlined, UploadOutlined, EditOutlined, EyeOutlined, EyeInvisibleOutlined, DownOutlined } from '@ant-design/icons';
|
|
|
|
|
//const { Paragraph } = Typography;
|
|
|
|
|
const QuestionBank = () => {
|
|
|
|
|
const [selectedRowsState, setSelectedRows] = useState<API.RuleListItem[]>([]);
|
|
|
|
|
const [expandedDescRowKeys, setExpandedDescRowKeys] = useState<readonly ReactText[]>([]); // 展开解析设置
|
|
|
|
|
const [addType, setAddType] = useState(0);
|
|
|
|
|
const numbers = [];
|
|
|
|
|
for(let i=0;i<50;i++){
|
|
|
|
|
numbers.push({id: `${i}`})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const dataSource = [
|
|
|
|
|
{
|
|
|
|
|
id: 1,
|
|
|
|
|
name: '下面哪个词语能体现未来思维?',
|
|
|
|
|
type: '单选',
|
|
|
|
|
options: [
|
|
|
|
|
{label: '井底之蛙', value: 'A'},
|
|
|
|
|
{label: '鼠目寸光', value: 'B'},
|
|
|
|
|
{label: '未雨绸缪', value: 'C'},
|
|
|
|
|
{label: '即时行乐', value: 'D'},
|
|
|
|
|
],
|
|
|
|
|
|
|
|
|
|
time: '2022/12/12',
|
|
|
|
|
tag: '生涯理论',
|
|
|
|
|
course: '特质因素理论',
|
|
|
|
|
|
|
|
|
|
answer:'C',
|
|
|
|
|
desc: '该成语意思是天还没有下雨,先把门窗绑牢。比喻事先做好准备工作。该成语意思是天还没有下雨,先把门窗绑牢。比喻事先做好准备工作。该成语意思是天还没有下雨,先把门窗绑牢。比喻事先做好准备工作。该成语意思是天还没有下雨,先把门窗绑牢。比喻事先做好准备工作。',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
manual: true,
|
|
|
|
|
onSuccess: (result) => {
|
|
|
|
|
mutate(result);
|
|
|
|
|
},
|
|
|
|
|
id: 2,
|
|
|
|
|
name: 'Ant Design',
|
|
|
|
|
type: '多选',
|
|
|
|
|
image:
|
|
|
|
|
'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
|
|
|
|
|
desc: '我是一条测试的描述',
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const list = listData?.list || [];
|
|
|
|
|
|
|
|
|
|
const paginationProps = {
|
|
|
|
|
showSizeChanger: true,
|
|
|
|
|
showQuickJumper: true,
|
|
|
|
|
pageSize: 5,
|
|
|
|
|
total: list.length,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const showEditModal = (item: BasicListItemDataType) => {
|
|
|
|
|
setVisible(true);
|
|
|
|
|
setCurrent(item);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const deleteItem = (id: string) => {
|
|
|
|
|
postRun('remove', { id });
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const editAndDelete = (key: string | number, currentItem: BasicListItemDataType) => {
|
|
|
|
|
if (key === 'edit') showEditModal(currentItem);
|
|
|
|
|
else if (key === 'delete') {
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
title: '删除任务',
|
|
|
|
|
content: '确定删除该任务吗?',
|
|
|
|
|
okText: '确认',
|
|
|
|
|
cancelText: '取消',
|
|
|
|
|
onOk: () => deleteItem(currentItem.id),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const extraContent = (
|
|
|
|
|
<div className={styles.extraContent}>
|
|
|
|
|
<RadioGroup defaultValue="all">
|
|
|
|
|
<RadioButton value="all">全部</RadioButton>
|
|
|
|
|
<RadioButton value="progress">进行中</RadioButton>
|
|
|
|
|
<RadioButton value="waiting">等待中</RadioButton>
|
|
|
|
|
</RadioGroup>
|
|
|
|
|
<Search className={styles.extraContentSearch} placeholder="请输入" onSearch={() => ({})} />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const MoreBtn: React.FC<{
|
|
|
|
|
item: BasicListItemDataType;
|
|
|
|
|
}> = ({ item }) => (
|
|
|
|
|
<Dropdown
|
|
|
|
|
overlay={
|
|
|
|
|
<Menu onClick={({ key }) => editAndDelete(key, item)}>
|
|
|
|
|
<Menu.Item key="edit">编辑 1</Menu.Item>
|
|
|
|
|
<Menu.Item key="delete">删除</Menu.Item>
|
|
|
|
|
</Menu>
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
<a>
|
|
|
|
|
更多 <DownOutlined />
|
|
|
|
|
</a>
|
|
|
|
|
</Dropdown>
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const handleDone = () => {
|
|
|
|
|
setDone(false);
|
|
|
|
|
setVisible(false);
|
|
|
|
|
setCurrent({});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleSubmit = (values: BasicListItemDataType) => {
|
|
|
|
|
setDone(true);
|
|
|
|
|
const method = values?.id ? 'update' : 'add';
|
|
|
|
|
postRun(method, values);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
id: 3,
|
|
|
|
|
name: '蚂蚁金服体验科技',
|
|
|
|
|
type: '判断',
|
|
|
|
|
image:
|
|
|
|
|
'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
|
|
|
|
|
desc: '我是一条测试的描述',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 4,
|
|
|
|
|
name: 'TechUI',
|
|
|
|
|
type: '单选',
|
|
|
|
|
image:
|
|
|
|
|
'https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg',
|
|
|
|
|
desc: '我是一条测试的描述',
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div>
|
|
|
|
|
<PageContainer>
|
|
|
|
|
<div className={styles.standardList}>
|
|
|
|
|
<Card bordered={false}>
|
|
|
|
|
<Row>
|
|
|
|
|
<Col sm={8} xs={24}>
|
|
|
|
|
<Info title="我的待办" value="8个任务" bordered />
|
|
|
|
|
</Col>
|
|
|
|
|
<Col sm={8} xs={24}>
|
|
|
|
|
<Info title="本周任务平均处理时间" value="32分钟" bordered />
|
|
|
|
|
</Col>
|
|
|
|
|
<Col sm={8} xs={24}>
|
|
|
|
|
<Info title="本周完成任务数" value="24个任务" />
|
|
|
|
|
</Col>
|
|
|
|
|
</Row>
|
|
|
|
|
</Card>
|
|
|
|
|
|
|
|
|
|
<Card
|
|
|
|
|
className={styles.listCard}
|
|
|
|
|
bordered={false}
|
|
|
|
|
title="基本列表"
|
|
|
|
|
style={{ marginTop: 24 }}
|
|
|
|
|
bodyStyle={{ padding: '0 32px 40px 32px' }}
|
|
|
|
|
extra={extraContent}
|
|
|
|
|
>
|
|
|
|
|
<List
|
|
|
|
|
size="large"
|
|
|
|
|
rowKey="id"
|
|
|
|
|
loading={loading}
|
|
|
|
|
pagination={paginationProps}
|
|
|
|
|
dataSource={list}
|
|
|
|
|
renderItem={(item) => (
|
|
|
|
|
<List.Item
|
|
|
|
|
actions={[
|
|
|
|
|
<a
|
|
|
|
|
key="edit"
|
|
|
|
|
onClick={(e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
showEditModal(item);
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
编辑3
|
|
|
|
|
</a>,
|
|
|
|
|
<MoreBtn key="more" item={item} />,
|
|
|
|
|
]}
|
|
|
|
|
>
|
|
|
|
|
<List.Item.Meta
|
|
|
|
|
avatar={<Avatar src={item.logo} shape="square" size="large" />}
|
|
|
|
|
title={<a href={item.href}>{item.title}</a>}
|
|
|
|
|
description={item.subDescription}
|
|
|
|
|
/>
|
|
|
|
|
<ListContent data={item} />
|
|
|
|
|
</List.Item>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
</Card>
|
|
|
|
|
</div>
|
|
|
|
|
</PageContainer>
|
|
|
|
|
<Button
|
|
|
|
|
type="dashed"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
setVisible(true);
|
|
|
|
|
<PageContainer content={false} extraContent={false} className={styles.questionbank}>
|
|
|
|
|
<ProList<any>
|
|
|
|
|
itemLayout="vertical"
|
|
|
|
|
rowClassName='questionbank-list-item'
|
|
|
|
|
pagination={{
|
|
|
|
|
defaultPageSize: 10,
|
|
|
|
|
showSizeChanger: false,
|
|
|
|
|
}}
|
|
|
|
|
toolBarRender={() => {
|
|
|
|
|
const menu = (
|
|
|
|
|
<Menu onClick={(value)=>setAddType(value)}>
|
|
|
|
|
<Menu.Item key="1">单选</Menu.Item>
|
|
|
|
|
<Menu.Item key="2">多选</Menu.Item>
|
|
|
|
|
<Menu.Item key="3">判断</Menu.Item>
|
|
|
|
|
</Menu>
|
|
|
|
|
);
|
|
|
|
|
return [
|
|
|
|
|
<Dropdown overlay={menu}>
|
|
|
|
|
<Button>
|
|
|
|
|
<PlusOutlined /> 新建 <DownOutlined />
|
|
|
|
|
</Button>
|
|
|
|
|
</Dropdown>,
|
|
|
|
|
<Button key="remove" type="default" danger>
|
|
|
|
|
<DeleteOutlined /> 批量删除
|
|
|
|
|
</Button>,
|
|
|
|
|
<Button key="download" >
|
|
|
|
|
<DownloadOutlined /> 下载模板
|
|
|
|
|
</Button>,
|
|
|
|
|
<Button key="upload" >
|
|
|
|
|
<UploadOutlined /> 批量上传
|
|
|
|
|
</Button>,
|
|
|
|
|
];
|
|
|
|
|
}}
|
|
|
|
|
onRow={(record: any) => {
|
|
|
|
|
return {
|
|
|
|
|
onMouseEnter: () => {
|
|
|
|
|
console.log(record);
|
|
|
|
|
},
|
|
|
|
|
onClick: () => {
|
|
|
|
|
console.log(record);
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
}}
|
|
|
|
|
rowKey="id"
|
|
|
|
|
headerTitle={false}
|
|
|
|
|
tooltip={false}
|
|
|
|
|
dataSource={dataSource}
|
|
|
|
|
rowSelection={{
|
|
|
|
|
onChange: (_, selectedRows) => {
|
|
|
|
|
setSelectedRows(selectedRows);
|
|
|
|
|
},
|
|
|
|
|
}}
|
|
|
|
|
// grid={{ gutter: 16, column: 1 }}
|
|
|
|
|
showActions="always"
|
|
|
|
|
showExtra="always"
|
|
|
|
|
metas={{
|
|
|
|
|
title: {
|
|
|
|
|
dataIndex: 'name',
|
|
|
|
|
render: (text: React.ReactNode, record: T, index: number) => `1. ${text}`,
|
|
|
|
|
},
|
|
|
|
|
avatar: {
|
|
|
|
|
dataIndex: 'type',
|
|
|
|
|
valueType: 'text',
|
|
|
|
|
render: (text: React.ReactNode, record: T, index: number) => `[${record.type}]`,
|
|
|
|
|
},
|
|
|
|
|
description: {
|
|
|
|
|
dataIndex: 'options',
|
|
|
|
|
valueType: 'checkbox',
|
|
|
|
|
render: (text: React.ReactNode, record: T, index: number) => {
|
|
|
|
|
return (
|
|
|
|
|
<List
|
|
|
|
|
header={false}
|
|
|
|
|
footer={false}
|
|
|
|
|
bordered={false}
|
|
|
|
|
dataSource={record.options || []}
|
|
|
|
|
renderItem={item => (
|
|
|
|
|
<List.Item>
|
|
|
|
|
<Typography.Text mark={false}>{`${item?.value}. ${item?.label}`}</Typography.Text>
|
|
|
|
|
</List.Item>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
subTitle: { },
|
|
|
|
|
content: {
|
|
|
|
|
render: (text: React.ReactNode, record: T, index: number) => {
|
|
|
|
|
return (
|
|
|
|
|
<Space direction="vertical" style={{border:'solid 1px #f0f0f0;',padding:10}}>
|
|
|
|
|
<Typography>正确答案:{record.answer}</Typography>
|
|
|
|
|
<Typography>解析:{record.desc}</Typography>
|
|
|
|
|
</Space>
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
actions: {
|
|
|
|
|
cardActionProps: 'extra',
|
|
|
|
|
render: (text: React.ReactNode, record: T, _index: number) => {
|
|
|
|
|
return(
|
|
|
|
|
<Row style={{padding:'10px 24px'}}>
|
|
|
|
|
<Col flex={1} style={{textAlign:'left'}}>
|
|
|
|
|
<Space direction="horizontal" size="large">
|
|
|
|
|
<Typography>创建时间:{record.time}</Typography>
|
|
|
|
|
<Typography>标签:{record.tag}</Typography>
|
|
|
|
|
<Typography>所属课程:{record.course}</Typography>
|
|
|
|
|
</Space>
|
|
|
|
|
</Col>
|
|
|
|
|
<Col flex={1} style={{textAlign:'right'}}>
|
|
|
|
|
<Space direction="horizontal" size="middle">
|
|
|
|
|
<a href={record.html_url} target="_blank" rel="noopener noreferrer" key="link">
|
|
|
|
|
<EditOutlined /> 编辑
|
|
|
|
|
</a>
|
|
|
|
|
<a href={record.html_url} target="_blank" rel="noopener noreferrer" key="warning">
|
|
|
|
|
<DeleteOutlined /> 删除
|
|
|
|
|
</a>
|
|
|
|
|
<a
|
|
|
|
|
key="view"
|
|
|
|
|
onClick={()=>{
|
|
|
|
|
setExpandedDescRowKeys([...expandedDescRowKeys, record.id]);
|
|
|
|
|
console.log('record id:', record.id);
|
|
|
|
|
console.log('expandedDescRowKeys', expandedDescRowKeys)
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<EyeOutlined /> <EyeInvisibleOutlined /> 查看解析
|
|
|
|
|
</a>
|
|
|
|
|
</Space>
|
|
|
|
|
</Col>
|
|
|
|
|
</Row>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}}
|
|
|
|
|
style={{ width: '100%', marginBottom: 8 }}
|
|
|
|
|
>
|
|
|
|
|
<PlusOutlined />
|
|
|
|
|
添加
|
|
|
|
|
</Button>
|
|
|
|
|
<OperationModal
|
|
|
|
|
done={done}
|
|
|
|
|
visible={visible}
|
|
|
|
|
current={current}
|
|
|
|
|
onDone={handleDone}
|
|
|
|
|
onSubmit={handleSubmit}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</PageContainer>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default BasicList;
|
|
|
|
|
export default QuestionBank;
|
|
|
|
|