思路
代码
redux版本\store\action-types.js
export const TASK_LIST = 'TASK_LIST'
export const TASK_REMOVE = 'TASK_REMOVE'
export const TASK_UPDATE = 'TASK_UPDATE'
redux版本\store\reducer\taskReducer.js
import { TASK_LIST, TASK_REMOVE, TASK_UPDATE } from '../action-types'
import _ from '@/assets/utils'
let initial = {
// 记录从服务器获取的全部任务
list: null,
}
export default function taskReducer(state = initial, action) {
// 自己封装的深克隆方法
state = _.clone(true, state)
let { type, payload, id } = action
// 同步全部任务
if (type === TASK_LIST) {
state.list = payload
}
if (Array.isArray(state.list)) {
// 删除指定任务
if (type === TASK_REMOVE) {
state.list = state.list.filter((item) => {
return +item.id !== +id
})
}
// 修改指定任务
if (type === TASK_UPDATE) {
state.list = state.list.map((item) => {
if (+item.id === +id) {
item.state = 2
item.complete = new Date().toLocaleString('zh-CN', { hour12: false })
}
return item
})
}
}
return state
}
redux版本\store\reducer\index.js
import { combineReducers } from 'redux'
import taskReducer from './taskReducer'
const reducer = combineReducers({
task: taskReducer,
})
export default reducer
redux版本\store\index.js
import { createStore, applyMiddleware } from 'redux'
import reducer from './reducer'
import reduxLogger from 'redux-logger' //在控制台输出派发日志
import reduxThunk from 'redux-thunk' //实现异步派发
import reduxPromise from 'redux-promise' //实现异步派发
// pplyMiddleware:中间键
const store = createStore(
reducer,
applyMiddleware(reduxLogger, reduxThunk, reduxPromise))
export default store
redux版本\store\actions\taskAction.js
import { TASK_LIST, TASK_REMOVE, TASK_UPDATE } from '../action-types'
import api from '@/api'
const taskAction = {
// redux-promise
async getTaskList() {
let result = {}
try {
result = await api.queryList()
if (+result.code !== 0) result.list = []
} catch (_) {
result.list = []
}
return {
type: TASK_LIST,
payload: result.list,
}
},
// redux-thunk
getTaskListThunk() {
return async (dispath) => {
try {
let { code, list } = await api.queryList()
if (+code !== 0) list = []
dispath({
type: TASK_LIST,
payload: list,
})
} catch (_) {
dispath({
type: TASK_LIST,
payload: [],
})
}
}
},
removeTask(id) {
return {
type: TASK_REMOVE,
id,
}
},
completeTask(id) {
return {
type: TASK_UPDATE,
id,
}
},
}
export default taskAction
redux版本\store\actions\index.js
const actions = {
task: taskAction,
}
export default actions
redux版本\index.jsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import Task from '@/views/Task'
/* ANTD */
import { ConfigProvider } from 'antd'
import zhCN from 'antd/lib/locale/zh_CN'
import './index.less'
/* REDUX */
import store from './store'
import { Provider } from 'react-redux'
const root = ReactDOM.createRoot(document.getElementById('root'))
root.render(
<ConfigProvider locale={zhCN}>
<Provider store={store}>
<Task />
</Provider>
</ConfigProvider>
)
redux版本\views\Task.jsx
import React, { useState, useEffect } from 'react'
import { Button, DatePicker, Form, Input, Modal, Popconfirm, Table, Tag, message } from 'antd'
import api from '@/api'
import './Task.less'
import { connect } from 'react-redux'
import actions from '@/store/actions'
// 时间格式化的方法
const formatTime = (time, template = '{0}-{1}-{2} {3}:{4}:{5}') => {
let arr = time.match(/\d+/g)
return template.replace(/\{(\d+)\}/g, (_, $1) => {
let item = arr[$1] || '00'
if (item.length < 2) item = '0' + item
return item
})
}
const Task = function Task(props) {
/* 定义表格列 */
const columns = [
{
title: '编号',
dataIndex: 'id',
align: 'center',
width: '8%',
},
{
title: '任务描述',
dataIndex: 'task',
width: '50%',
},
{
title: '状态',
dataIndex: 'state',
align: 'center',
width: '10%',
render: (text) => (+text === 1 ? '未完成' : '已完成'),
},
{
title: '完成时间',
dataIndex: 'time',
align: 'center',
width: '15%',
render: (_, record) => {
let { state, time, complete } = record
time = +state === 1 ? time : complete
return formatTime(time, '{1}-{2} {3}:{4}')
},
},
{
title: '操作',
render: (_, record) => {
let { state, id } = record
return (
<>
<Popconfirm title="您确定要删除此任务吗?" onConfirm={removeHandler.bind(null, id)}>
<Button type="link">删除</Button>
</Popconfirm>
{+state === 1 ? (
<Popconfirm title="您确定要把此任务设置为完成吗?" onConfirm={updateHandler.bind(null, id)}>
<Button type="link">完成</Button>
</Popconfirm>
) : null}
</>
)
},
},
]
/* 定义状态 */
let [tableData, setTableData] = useState([]),
[loading, setLoading] = useState(false),
[selected, setSelected] = useState(0),
[visible, setVisible] = useState(false),
[confirmLoading, setConfirmLoading] = useState(false),
[formIns] = Form.useForm()
let { list, getTaskList, getTaskListThunk, removeTask, completeTask } = props
/* 获取数据 */
useEffect(() => {
const init = async () => {
// 判断公共状态是否存在:不存在则完成异步派发
// !null=true ![]=false
if (!list) {
// list 不存在
setLoading(true)
await getTaskList()
setLoading(false)
return
}
// 存在则筛选想要的数据给TABLE
let temp = list
if (selected !== 0) {
temp = temp.filter((item) => {
return +item.state === selected
})
}
setTableData(temp)
}
init()
// 除了依赖选中,还依赖于redux的公共状态
}, [selected, list])
/* 页卡切换 */
const changeTabHandler = (index) => {
if (selected === index) return
setSelected(index)
}
/* 关闭Modal && 提交信息 */
const cancelHandler = () => {
setVisible(false)
setConfirmLoading(false)
formIns.resetFields()
}
const submitHandler = async () => {
try {
await formIns.validateFields()
// 向服务器提交数据
setConfirmLoading(true)
let { task, time } = formIns.getFieldsValue()
time = time.format('YYYY-MM-DD HH:mm:ss')
let { code } = await api.addTask({
task,
time,
})
if (+code !== 0) {
message.error('很遗憾,当前操作失败~')
} else {
message.success('恭喜您,当前操作成功~')
cancelHandler()
// 异步派发
setLoading(true)
await getTaskListThunk()
setLoading(false)
}
} catch (_) {}
setConfirmLoading(false)
}
/* 删除 && 完成 */
const removeHandler = async (id) => {
try {
let { code } = await api.removeTask(id)
if (+code !== 0) {
message.error('很遗憾,当前操作失败~')
return
}
message.success('恭喜您,当前操作成功~')
// 同步派发
removeTask(id)
} catch (_) {}
}
const updateHandler = async (id) => {
try {
let { code } = await api.completeTask(id)
if (+code !== 0) {
message.error('很遗憾,当前操作失败~')
return
}
message.success('恭喜您,当前操作成功~')
// 同步派发
completeTask(id)
} catch (_) {}
}
return (
<div className="task-box">
<header className="head-box">
<h2 className="title">TASK OA 任务管理系统</h2>
<Button type="primary" onClick={() => setVisible(true)}>
新增任务
</Button>
</header>
<section className="tag-box">
{['全部', '未完成', '已完成'].map((item, index) => {
return (
<Tag key={index} color={selected === index ? '#108ee9' : ''} onClick={changeTabHandler.bind(null, index)}>
{item}
</Tag>
)
})}
</section>
<Table pagination={false} rowKey="id" loading={loading} dataSource={tableData} columns={columns} />
<Modal
title="新增任务窗口"
okText="提交信息"
maskClosable={false}
keyboard={false}
visible={visible}
confirmLoading={confirmLoading}
onCancel={cancelHandler}
onOk={submitHandler}
>
<Form layout="vertical" form={formIns} initialValues={{ task: '', time: '' }}>
<Form.Item
label="任务描述"
name="task"
validateTrigger="onBlur"
rules={[{ required: true, pattern: /^[\w\W]{6,}$/, message: '任务描述必须在6位以上~' }]}
>
<Input.TextArea rows={4} />
</Form.Item>
<Form.Item
label="任务预期完成时间"
name="time"
validateTrigger="onBlur"
rules={[{ required: true, message: '任务完成时间是必填项~' }]}
>
<DatePicker showTime />
</Form.Item>
</Form>
</Modal>
</div>
)
}
export default connect((state) => state.task, actions.task)(Task)
redux版本\api\http.js
import axios from 'axios'
import qs from 'qs'
import { message } from 'antd'
import utils from '@/assets/utils'
const http = axios.create({
baseURL: '/api',
timeout: 60000,
})
http.defaults.transformRequest = (data) => {
if (utils.isPlainObject(data)) data = qs.stringify(data)
return data
}
http.interceptors.response.use(
(response) => {
return response.data
},
(reason) => {
message.error('当前网络繁忙,请您稍后再试~')
return Promise.reject(reason)
}
)
export default http
redux版本\api\index.js
import http from './http'
// 获取指定状态的任务列表
const queryList = (state = 0) => {
return http.get('/getTaskList', {
params: {
state,
},
})
}
// 新增任务
const addTask = (data) => http.post('/addTask', data)
// 删除任务
const removeTask = (id) => {
return http.get('/removeTask', {
params: {
id,
},
})
}
// 完成任务
const completeTask = (id) => {
return http.get('/completeTask', {
params: {
id,
},
})
}
export default {
queryList,
addTask,
removeTask,
completeTask,
}