有些公司会有支持度问题,所以这里我们用传统的方式。
RAP2rap2.taobao.org保存!!
有些时候,后端会说删除的是那篇文章,就是id。
后端的删除是分为:逻辑删除和物理删除的。
逻辑删除的话,会做一个标识,会有一个回收站。
物理删除的话,直接从数据库里面删除。
在 requests 文件下的 index.js :
//通过id删除文章
//第一种方式
export const deleteArticle = (id) => {
return service.post(`/api/vi/articleDlete`)
id
}
//第二种方式
export const deleteArticle = (id) => {
return service.post(`/api/vi/articleDlete/${id}`)
}
去 Aticle 下面的 index.js :
import { getArticles,deleteArticle } from '../../requests'
下一步
删除文章
import axios from 'axios'
import { message } from 'antd'
const isDev = process.env.NODE_ENV === 'development'
const service = axios.create({
baseURL: isDev ? 'http://rap2api.taobao.org/app/mock/176929' : ''
})
//请求拦截器
service.interceptors.request.use((config) => {
config.data = Object.assign({}, config.data, {
// authToken: window.localStorage.getItem('authToken')
authToken: 'itisatokenplaceholder'
})
return config
})
service.interceptors.response.use((resp) => {
if (resp.data.code === 200) {
return resp.data.data
} else {
// 全局处理错误
message.error(resp.data.errMsg)
}
})
// 获取文章列表
export const getArticles = (offset = 0, limited = 10) => {
return service.post('/api/v1/articleList', {
offset,
limited
})
}
//通过id删除文章
export const deleteArticle = (id) => {
return service.post(`/api/v1/articleDelete`,{id})
}
Article 下的 index.js:
import React, { Component } from 'react'
import moment from 'moment'
// eslint-disable-next-line
import XLSX from 'xlsx'
import {
Card,
Button,
Table,
Tag,
Modal,
Typography
} from 'antd';
import { getArticles,deleteArticle } from '../../requests'
const ButtonGroup = Button.Group
const titleDisplayMap={
id:'id',
title:'标题',
author:'作者',
createAt:'创建时间',
amount:'阅读量'
}
export default class ArticleList extends Component {
constructor(){
super()
this.state={
dataSource: [
//初始化的数据暂时不用了
],
total:0,
isLoading:false,
//默认从多少开始
offset:0,
limited:10
}
}
createColumns = (columnKeys) => {
const columns = columnKeys.map(item => {
if (item === 'amount') {
return {
title: titleDisplayMap[item],
key: item,
render: (text, record) => {
const { amount } = record
// 这里是根据一个数字的大小做一个条件渲染
// 同理,可以做职位级别不同的颜色
// 总经理:'001',经理:'002',主管: '003'
// const titleMap = {
// '001': 'red',
// '002': '#09f',
// '003': 'green'
// }
// return <Tag color={titleMap[titleKey]}>{record.title}</Tag>
return <Tag color={amount > 230 ? 'red' : 'green'}>{record.amount}</Tag>
}
}
}
if(item === 'createAt'){
return {
title: titleDisplayMap[item],
key: item,
render: (text, record) => {
const { createAt } = record
return moment(createAt).format('YYYY年MM月DD日 hh:mm:ss')
}
}
}
return {
title:titleDisplayMap[item],
dataIndex:item,
key:item
}
})
columns.push({
title:'操作',
key:'action',
render:(text, record) => {
return (
<ButtonGroup>
<Button size="small" type="primary">编辑</Button>
<Button size="small" type="danger" onClick={this.deleteArticle.bind(this, record)}>删除</Button>
</ButtonGroup>
)
}
})
return columns
}
deleteArticle = (record) => {
// console.log({id})
Modal.confirm({
title:'此操作不可逆,请谨慎!',
content:<Typography>确定要删除<span style={{color:'#f00'}}>{record.title}</span>吗?</Typography>,
okText:'别磨叽,赶紧删!',
cancelText:'我点错了',
onOk(){
deleteArticle(record.id)
.then(resp => {
console.log(resp)
})
}
})
}
getData = () => {
this.setState({
isLoading:true
})
getArticles(this.state.offset, this.state.limited)
.then(resp => {
const columnKeys=Object.keys(resp.list[0])
const columns=this.createColumns(columnKeys)
this.setState ({
total:resp.total,
dataSource:resp.list,
columns,
})
})
.catch(ree => {
//,处理错误,虽然有全局处理
})
.finally(() => {
this.setState({
isLoading:false
})
})
}
//分页
onPageChange = (page, pageSize) => {
console.log({page, pageSize})
this.setState({
offset:pageSize * (page - 1),
limited:pageSize
},() => {
this.getData()
})
}
onShowSizeChange = (current,size) => {
//这里要注意和产品聊好需求,回到第一页还是留在当前页
console.log({current,size})
this.setState({
offset:0,
limited:size
},() => {
this.getData()
})
}
toExcel = () => {
//在实际项目中,实际上这个功能是前端发送一个ajax请求到后端,然后后端返回一个文件下载的地址。
//组合数据
const data=[Object.keys(this.state.dataSource[0])] //[['id','title','author','amount','createAt']]
for (let i = 0; i < this.state.dataSource.length; i++){
// data.push(Object.values(this.state.dataSource[i])) 这样写有些不好
data.push([
this.state.dataSource[i].id,
this.state.dataSource[i].title,
this.state.dataSource[i].author,
this.state.dataSource[i].amount,
moment(this.state.dataSource[i].createAt).format('YYYY年MM月DD日 hh:mm:ss')
])
}
const ws=XLSX.utils.aoa_to_sheet(data)
const wb=XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, "SheetJS")
// XLSX.writeFile(wb, "sheetjs.xlsx")
XLSX.writeFile(wb, `articles-${this.state.offset / this.state.limited + 1}-${moment().format('YYYYMMDDHHmmss')}.xlsx`)
}
componentDidMount(){
this.getData()
}
render() {
return (
<Card
title="文章列表"
bordered={false}
extra={<Button onClick={this.toExcel}>导出excel</Button>}
>
<Table
rowKey={record => record.id}
dataSource={this.state.dataSource}
columns={this.state.columns}
loading={this.state.isLoading}
pagination={{
current:this.state.offset / this.state.limited + 1,
total:this.state.total,
hideOnSinglePage:true,
showQuickJumper:true,
showSizeChanger:true,
onChange:this.onPageChange,
onShowSizeChange:this.onShowSizeChange,
pageSizeOptions:['10', '15', '20', '30']
}}
/>
</Card>
)
}
}
之前有一个小错误,现在改正了。
Article 下的 index.js:
deleteArticle = (record) => {
// console.log({id})
Modal.confirm({
title:'此操作不可逆,请谨慎!',
content:<Typography>确定要删除<span style={{color:'#f00'}}>{record.title}</span>吗?</Typography>,
okText:'别磨叽,赶紧删!',
cancelText:'我点错了',
onCancel(){
console.log('aa')
},
onOk(){
deleteArticle(record.id)
.then(resp => {
console.log(resp)
})
}
})
}
按钮部分改动为手动关闭,而不是直接关闭
import React, { Component } from 'react'
import moment from 'moment'
// eslint-disable-next-line
import XLSX from 'xlsx'
import {
Card,
Button,
Table,
Tag,
Modal,
Typography
} from 'antd';
import { getArticles,deleteArticle } from '../../requests'
const ButtonGroup = Button.Group
const titleDisplayMap={
id:'id',
title:'标题',
author:'作者',
createAt:'创建时间',
amount:'阅读量'
}
export default class ArticleList extends Component {
constructor(){
super()
this.state={
dataSource: [
//初始化的数据暂时不用了
],
total:0,
isLoading:false,
//默认从多少开始
offset:0,
limited:10
}
}
createColumns = (columnKeys) => {
const columns = columnKeys.map(item => {
if (item === 'amount') {
return {
title: titleDisplayMap[item],
key: item,
render: (text, record) => {
const { amount } = record
// 这里是根据一个数字的大小做一个条件渲染
// 同理,可以做职位级别不同的颜色
// 总经理:'001',经理:'002',主管: '003'
// const titleMap = {
// '001': 'red',
// '002': '#09f',
// '003': 'green'
// }
// return <Tag color={titleMap[titleKey]}>{record.title}</Tag>
return <Tag color={amount > 230 ? 'red' : 'green'}>{record.amount}</Tag>
}
}
}
if(item === 'createAt'){
return {
title: titleDisplayMap[item],
key: item,
render: (text, record) => {
const { createAt } = record
return moment(createAt).format('YYYY年MM月DD日 hh:mm:ss')
}
}
}
return {
title:titleDisplayMap[item],
dataIndex:item,
key:item
}
})
columns.push({
title:'操作',
key:'action',
render:(text, record) => {
return (
<ButtonGroup>
<Button size="small" type="primary">编辑</Button>
<Button size="small" type="danger" onClick={this.deleteArticle.bind(this, record)}>删除</Button>
</ButtonGroup>
)
}
})
return columns
}
deleteArticle = (record) => {
// console.log({id})
// Modal.confirm({
// title:'此操作不可逆,请谨慎!',
// content:<Typography>确定要删除<span style={{color:'#f00'}}>{record.title}</span>吗?</Typography>,
// okText:'别磨叽,赶紧删!',
// cancelText:'我点错了',
// onCancel(){
// console.log('aa')
// },
// onOk(){
// deleteArticle(record.id)
// .then(resp => {
// console.log(resp)
// })
// }
// })
}
getData = () => {
this.setState({
isLoading:true
})
getArticles(this.state.offset, this.state.limited)
.then(resp => {
const columnKeys=Object.keys(resp.list[0])
const columns=this.createColumns(columnKeys)
this.setState ({
total:resp.total,
dataSource:resp.list,
columns,
})
})
.catch(ree => {
//,处理错误,虽然有全局处理
})
.finally(() => {
this.setState({
isLoading:false
})
})
}
//分页
onPageChange = (page, pageSize) => {
console.log({page, pageSize})
this.setState({
offset:pageSize * (page - 1),
limited:pageSize
},() => {
this.getData()
})
}
onShowSizeChange = (current,size) => {
//这里要注意和产品聊好需求,回到第一页还是留在当前页
console.log({current,size})
this.setState({
offset:0,
limited:size
},() => {
this.getData()
})
}
toExcel = () => {
//在实际项目中,实际上这个功能是前端发送一个ajax请求到后端,然后后端返回一个文件下载的地址。
//组合数据
const data=[Object.keys(this.state.dataSource[0])] //[['id','title','author','amount','createAt']]
for (let i = 0; i < this.state.dataSource.length; i++){
// data.push(Object.values(this.state.dataSource[i])) 这样写有些不好
data.push([
this.state.dataSource[i].id,
this.state.dataSource[i].title,
this.state.dataSource[i].author,
this.state.dataSource[i].amount,
moment(this.state.dataSource[i].createAt).format('YYYY年MM月DD日 hh:mm:ss')
])
}
const ws=XLSX.utils.aoa_to_sheet(data)
const wb=XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, "SheetJS")
// XLSX.writeFile(wb, "sheetjs.xlsx")
XLSX.writeFile(wb, `articles-${this.state.offset / this.state.limited + 1}-${moment().format('YYYYMMDDHHmmss')}.xlsx`)
}
componentDidMount(){
this.getData()
}
render() {
return (
<Card
title="文章列表"
bordered={false}
extra={<Button onClick={this.toExcel}>导出excel</Button>}
>
<Table
rowKey={record => record.id}
dataSource={this.state.dataSource}
columns={this.state.columns}
loading={this.state.isLoading}
pagination={{
current:this.state.offset / this.state.limited + 1,
total:this.state.total,
hideOnSinglePage:true,
showQuickJumper:true,
showSizeChanger:true,
onChange:this.onPageChange,
onShowSizeChange:this.onShowSizeChange,
pageSizeOptions:['10', '15', '20', '30']
}}
/>
<Modal
title='此操作不可逆,请谨慎!'
content="aaaaa"
visible={true}
/>
</Card>
)
}
}
结果会弹出框,但点击确认、取消都不执行
正规用法:
import React, { Component } from 'react'
import moment from 'moment'
// eslint-disable-next-line
import XLSX from 'xlsx'
import {
Card,
Button,
Table,
Tag,
Modal,
Typography
} from 'antd';
import { getArticles,deleteArticle } from '../../requests'
const ButtonGroup = Button.Group
const titleDisplayMap={
id:'id',
title:'标题',
author:'作者',
createAt:'创建时间',
amount:'阅读量'
}
export default class ArticleList extends Component {
constructor(){
super()
this.state={
dataSource: [
//初始化的数据暂时不用了
],
total:0,
isLoading:false,
//默认从多少开始
offset:0,
limited:10,
//默认是空
deleteArticleTitle:'',
isShowArticleModal:false
}
}
createColumns = (columnKeys) => {
const columns = columnKeys.map(item => {
if (item === 'amount') {
return {
title: titleDisplayMap[item],
key: item,
render: (text, record) => {
const { amount } = record
// 这里是根据一个数字的大小做一个条件渲染
// 同理,可以做职位级别不同的颜色
// 总经理:'001',经理:'002',主管: '003'
// const titleMap = {
// '001': 'red',
// '002': '#09f',
// '003': 'green'
// }
// return <Tag color={titleMap[titleKey]}>{record.title}</Tag>
return <Tag color={amount > 230 ? 'red' : 'green'}>{record.amount}</Tag>
}
}
}
if(item === 'createAt'){
return {
title: titleDisplayMap[item],
key: item,
render: (text, record) => {
const { createAt } = record
return moment(createAt).format('YYYY年MM月DD日 hh:mm:ss')
}
}
}
return {
title:titleDisplayMap[item],
dataIndex:item,
key:item
}
})
columns.push({
title:'操作',
key:'action',
render:(text, record) => {
return (
<ButtonGroup>
<Button size="small" type="primary">编辑</Button>
<Button size="small" type="danger" onClick={this.deleteArticle.bind(this, record)}>删除</Button>
</ButtonGroup>
)
}
})
return columns
}
deleteArticle = (record) => {
// console.log({id})
//使用函数式的方式调用,定制化没有那么强
// Modal.confirm({
// title:'此操作不可逆,请谨慎!',
// content:<Typography>确定要删除<span style={{color:'#f00'}}>{record.title}</span>吗?</Typography>,
// okText:'别磨叽,赶紧删!',
// cancelText:'我点错了',
// onCancel(){
// console.log('aa')
// },
// onOk(){
// deleteArticle(record.id)
// .then(resp => {
// console.log(resp)
// })
// }
// })
this.setState({
isShowArticleModal:true,
deleteArticleTitle:record.title
})
}
getData = () => {
this.setState({
isLoading:true
})
getArticles(this.state.offset, this.state.limited)
.then(resp => {
const columnKeys=Object.keys(resp.list[0])
const columns=this.createColumns(columnKeys)
this.setState ({
total:resp.total,
dataSource:resp.list,
columns,
})
})
.catch(ree => {
//,处理错误,虽然有全局处理
})
.finally(() => {
this.setState({
isLoading:false
})
})
}
//分页
onPageChange = (page, pageSize) => {
console.log({page, pageSize})
this.setState({
offset:pageSize * (page - 1),
limited:pageSize
},() => {
this.getData()
})
}
onShowSizeChange = (current,size) => {
//这里要注意和产品聊好需求,回到第一页还是留在当前页
console.log({current,size})
this.setState({
offset:0,
limited:size
},() => {
this.getData()
})
}
toExcel = () => {
//在实际项目中,实际上这个功能是前端发送一个ajax请求到后端,然后后端返回一个文件下载的地址。
//组合数据
const data=[Object.keys(this.state.dataSource[0])] //[['id','title','author','amount','createAt']]
for (let i = 0; i < this.state.dataSource.length; i++){
// data.push(Object.values(this.state.dataSource[i])) 这样写有些不好
data.push([
this.state.dataSource[i].id,
this.state.dataSource[i].title,
this.state.dataSource[i].author,
this.state.dataSource[i].amount,
moment(this.state.dataSource[i].createAt).format('YYYY年MM月DD日 hh:mm:ss')
])
}
const ws=XLSX.utils.aoa_to_sheet(data)
const wb=XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, "SheetJS")
// XLSX.writeFile(wb, "sheetjs.xlsx")
XLSX.writeFile(wb, `articles-${this.state.offset / this.state.limited + 1}-${moment().format('YYYYMMDDHHmmss')}.xlsx`)
}
componentDidMount(){
this.getData()
}
render() {
return (
<Card
title="文章列表"
bordered={false}
extra={<Button onClick={this.toExcel}>导出excel</Button>}
>
<Table
rowKey={record => record.id}
dataSource={this.state.dataSource}
columns={this.state.columns}
loading={this.state.isLoading}
pagination={{
current:this.state.offset / this.state.limited + 1,
total:this.state.total,
hideOnSinglePage:true,
showQuickJumper:true,
showSizeChanger:true,
onChange:this.onPageChange,
onShowSizeChange:this.onShowSizeChange,
pageSizeOptions:['10', '15', '20', '30']
}}
/>
<Modal
title='此操作不可逆,请谨慎!'
visible={this.state.isShowArticleModal}
>
<Typography>确定要删除<span style={{color:'#f00'}}>{this.state.deleteArticleTitle}</span>吗?</Typography>
</Modal>
</Card>
)
}
}
下面做,点击后关闭
import React, { Component } from 'react'
import moment from 'moment'
// eslint-disable-next-line
import XLSX from 'xlsx'
import {
Card,
Button,
Table,
Tag,
Modal,
Typography
} from 'antd';
import { getArticles,deleteArticle } from '../../requests'
const ButtonGroup = Button.Group
const titleDisplayMap={
id:'id',
title:'标题',
author:'作者',
createAt:'创建时间',
amount:'阅读量'
}
export default class ArticleList extends Component {
constructor(){
super()
this.state={
dataSource: [
//初始化的数据暂时不用了
],
total:0,
isLoading:false,
//默认从多少开始
offset:0,
limited:10,
//默认是空
deleteArticleTitle:'',
isShowArticleModal:false
}
}
createColumns = (columnKeys) => {
const columns = columnKeys.map(item => {
if (item === 'amount') {
return {
title: titleDisplayMap[item],
key: item,
render: (text, record) => {
const { amount } = record
// 这里是根据一个数字的大小做一个条件渲染
// 同理,可以做职位级别不同的颜色
// 总经理:'001',经理:'002',主管: '003'
// const titleMap = {
// '001': 'red',
// '002': '#09f',
// '003': 'green'
// }
// return <Tag color={titleMap[titleKey]}>{record.title}</Tag>
return <Tag color={amount > 230 ? 'red' : 'green'}>{record.amount}</Tag>
}
}
}
if(item === 'createAt'){
return {
title: titleDisplayMap[item],
key: item,
render: (text, record) => {
const { createAt } = record
return moment(createAt).format('YYYY年MM月DD日 hh:mm:ss')
}
}
}
return {
title:titleDisplayMap[item],
dataIndex:item,
key:item
}
})
columns.push({
title:'操作',
key:'action',
render:(text, record) => {
return (
<ButtonGroup>
<Button size="small" type="primary">编辑</Button>
<Button size="small" type="danger" onClick={this.deleteArticle.bind(this, record)}>删除</Button>
</ButtonGroup>
)
}
})
return columns
}
deleteArticle = (record) => {
//使用函数式的方式调用,定制化没有那么强
this.setState({
isShowArticleModal:true,
deleteArticleTitle:record.title
})
}
hideDeleteModal = () =>{
this.setState({
isShowArticleModal:false,
deleteArticleTitle:''
})
}
getData = () => {
this.setState({
isLoading:true
})
getArticles(this.state.offset, this.state.limited)
.then(resp => {
const columnKeys=Object.keys(resp.list[0])
const columns=this.createColumns(columnKeys)
this.setState ({
total:resp.total,
dataSource:resp.list,
columns,
})
})
.catch(ree => {
//,处理错误,虽然有全局处理
})
.finally(() => {
this.setState({
isLoading:false
})
})
}
//分页
onPageChange = (page, pageSize) => {
console.log({page, pageSize})
this.setState({
offset:pageSize * (page - 1),
limited:pageSize
},() => {
this.getData()
})
}
onShowSizeChange = (current,size) => {
//这里要注意和产品聊好需求,回到第一页还是留在当前页
console.log({current,size})
this.setState({
offset:0,
limited:size
},() => {
this.getData()
})
}
toExcel = () => {
//在实际项目中,实际上这个功能是前端发送一个ajax请求到后端,然后后端返回一个文件下载的地址。
//组合数据
const data=[Object.keys(this.state.dataSource[0])] //[['id','title','author','amount','createAt']]
for (let i = 0; i < this.state.dataSource.length; i++){
data.push([
this.state.dataSource[i].id,
this.state.dataSource[i].title,
this.state.dataSource[i].author,
this.state.dataSource[i].amount,
moment(this.state.dataSource[i].createAt).format('YYYY年MM月DD日 hh:mm:ss')
])
}
const ws=XLSX.utils.aoa_to_sheet(data)
const wb=XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, "SheetJS")
// XLSX.writeFile(wb, "sheetjs.xlsx")
XLSX.writeFile(wb, `articles-${this.state.offset / this.state.limited + 1}-${moment().format('YYYYMMDDHHmmss')}.xlsx`)
}
componentDidMount(){
this.getData()
}
render() {
return (
<Card
title="文章列表"
bordered={false}
extra={<Button onClick={this.toExcel}>导出excel</Button>}
>
<Table
rowKey={record => record.id}
dataSource={this.state.dataSource}
columns={this.state.columns}
loading={this.state.isLoading}
pagination={{
current:this.state.offset / this.state.limited + 1,
total:this.state.total,
hideOnSinglePage:true,
showQuickJumper:true,
showSizeChanger:true,
onChange:this.onPageChange,
onShowSizeChange:this.onShowSizeChange,
pageSizeOptions:['10', '15', '20', '30']
}}
/>
<Modal
title='此操作不可逆,请谨慎!'
visible={this.state.isShowArticleModal}
onCancel={this.hideDeleteModal}
>
<Typography>
确定要删除<span style={{color:'#f00'}}>{this.state.deleteArticleTitle}</span>吗?
</Typography>
</Modal>
</Card>
)
}
}
取消和 x 按钮的取消,都做好了
这样做,按钮就是单独控制的!之前的ui是按钮直接取消了。
over