功能描述
社团开展活动时往往会申请可用的场地来作为自己的活动地点,而这就需要社联对场地进行合理的管理。在此之前社联一直采用人工登记的方式来对场地进行分配,我们认为这一方法不仅耗时而且容易出现差错,因此本项目希望实现可视化场地查询功能,社团人员可以直接查找自己活动日期的空闲场地,找到想要的场地之后直接进行预约,这样既方便了社团活动人员,也方便了社联管理者。
功能设计
怎样将可视化的场地信息表示出来是此功能的核心问题。衡量一个场地需要三个要素:场地地点,场地使用日期,场地使用具体时间(精确到小时),起初我们参考过如下图的设计:
即用一张图表示地点,日期,小时要素,但在精确细分小时的前提下将社联提供的几十个活动场地插入表格后,该表会变得异常庞大,十分影响美观,也不利于操作。因此我们决定将表的内容做适当拆分,在让用户可以自由选择地点,日期,小时的前提下进行适当美化,最终的设计大致如下:
同时在地点,日期,小时上均提供搜索功能,这样用户就能精确检索到自己需要的场地:
功能实现
- 使用antd的表格组件完成整体框架的构建
<div>
<div style={{ marginBottom: 16 }}>
<Button type="primary" onClick={this.start} disabled={false} loading={loading}>
查询/刷新
</Button>
<span style={{ marginLeft: 8 }}>
{hasSelected ? `Selected ${selectedRowKeys.length} items` : ''}
</span>
</div>
<Table rowSelection={rowSelection} columns={columns} dataSource={data} pagination={Pagination}/>
</div>
- 通过 filterDropdown 实现自定义的列筛选功能
getColumnSearchProps = dataIndex => ({
filterDropdown: ({setSelectedKeys, selectedKeys, confirm, clearFilters}) => (
<div style={{padding: 8}}>
<Input
ref={node => {
this.searchInput = node;
}}
placeholder={`Search ${dataIndex}`}
value={selectedKeys[0]}
onChange={e => setSelectedKeys(e.target.value ? [e.target.value] : [])}
onPressEnter={() => this.handleSearch(selectedKeys, confirm, dataIndex)}
style={{ 188, marginBottom: 8, display: 'block'}}
/>
<Button
type="primary"
onClick={() => this.handleSearch(selectedKeys, confirm, dataIndex)}//定义搜索按钮
icon={<SearchOutlined/>}
size="small"
style={{ 90}}
>
Search
</Button>
<Button onClick={() => this.handleReset(clearFilters)} size="small" style={{ 90}}>//重置搜索框
Reset
</Button>
</div>
),
filterIcon: filtered => <SearchOutlined style={{color: filtered ? '#1890ff' : undefined}}/>,
onFilter: (value, record) =>
record[dataIndex].toString().toLowerCase().includes(value.toLowerCase()),
onFilterDropdownVisibleChange: visible => {
if (visible) {
setTimeout(() => this.searchInput.select());
}
},
render: text =>
this.state.searchedColumn === dataIndex ? (
<Highlighter
highlightStyle={{backgroundColor: '#ffc069', padding: 0}}//高亮渲染显示搜索结果
searchWords={[this.state.searchText]}//搜索关键字
autoEscape
textToHighlight={text.toString()}
/>
) : (
text
),
});
handleSearch = (selectedKeys, confirm, dataIndex) => {
confirm();
this.setState({
searchText: selectedKeys[0],
searchedColumn: dataIndex,
});
};
handleReset = clearFilters => {
clearFilters();
this.setState({searchText: ''});
};
最后将自定义的列数据导入即可
- API设计:API的需求是返回目前已经被申请的所有地点,以及他们的申请日期与使用时间。可定义一个结构体,例如叫apply_place,apply_place.place表示地点,apply_place.date表示使用日期,apply_place.time表示具体时间,均为string类型。每一个apply_place表示下表中的一个条目,返回一个apply_place数组即可将所有条目返回。前端通过遍历apply_place数组就可以给所有被申请的条目打上标记。那么如何高效的找到标记的条目?给每个条目定义一个key即可,将地点,日期,时间数据按顺序导入的话,那么每一个条目的key都是固定的,也就是可以计算出来的,例如若(沙河-操场,6-1,8:00-9:00)的key为1,那么(沙河-操场,6-1,21:00-22:00)的key为14,(沙河-操场,6-2,8:00-9:00)的key为15(规定申请时间为8:00-22:00,使用1+14=15即可)、
var keyid = 1;
for (let j = 1; j <= 30; j++){
for (let k = 8; k <= 21; k++){
data.push({
key: keyid,
location: `沙河-百米跑廊`,
date: `6-${j}`,
time: `${k}:00-${k+1}:00`,
});
keyid++;
}
}