添加批量删除渠道功能

This commit is contained in:
CaIon 2023-12-14 16:35:03 +08:00
parent 0fdd4fc6e3
commit e1da1e31d5
4 changed files with 118 additions and 11 deletions

View File

@ -151,6 +151,36 @@ func DeleteDisabledChannel(c *gin.Context) {
return return
} }
type ChannelBatch struct {
Ids []int `json:"ids"`
}
func DeleteChannelBatch(c *gin.Context) {
channelBatch := ChannelBatch{}
err := c.ShouldBindJSON(&channelBatch)
if err != nil || len(channelBatch.Ids) == 0 {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": "参数错误",
})
return
}
err = model.BatchDeleteChannels(channelBatch.Ids)
if err != nil {
c.JSON(http.StatusOK, gin.H{
"success": false,
"message": err.Error(),
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "",
"data": len(channelBatch.Ids),
})
return
}
func UpdateChannel(c *gin.Context) { func UpdateChannel(c *gin.Context) {
channel := model.Channel{} channel := model.Channel{}
err := c.ShouldBindJSON(&channel) err := c.ShouldBindJSON(&channel)

View File

@ -86,6 +86,25 @@ func BatchInsertChannels(channels []Channel) error {
return nil return nil
} }
func BatchDeleteChannels(ids []int) error {
//使用事务 删除channel表和channel_ability表
tx := DB.Begin()
err := tx.Where("id in (?)", ids).Delete(&Channel{}).Error
if err != nil {
// 回滚事务
tx.Rollback()
return err
}
err = tx.Where("channel_id in (?)", ids).Delete(&Ability{}).Error
if err != nil {
// 回滚事务
tx.Rollback()
}
// 提交事务
tx.Commit()
return err
}
func (channel *Channel) GetPriority() int64 { func (channel *Channel) GetPriority() int64 {
if channel.Priority == nil { if channel.Priority == nil {
return 0 return 0

View File

@ -83,6 +83,7 @@ func SetApiRouter(router *gin.Engine) {
channelRoute.PUT("/", controller.UpdateChannel) channelRoute.PUT("/", controller.UpdateChannel)
channelRoute.DELETE("/disabled", controller.DeleteDisabledChannel) channelRoute.DELETE("/disabled", controller.DeleteDisabledChannel)
channelRoute.DELETE("/:id", controller.DeleteChannel) channelRoute.DELETE("/:id", controller.DeleteChannel)
channelRoute.POST("/batch", controller.DeleteChannelBatch)
} }
tokenRoute := apiRouter.Group("/token") tokenRoute := apiRouter.Group("/token")
tokenRoute.Use(middleware.UserAuth()) tokenRoute.Use(middleware.UserAuth())

View File

@ -74,6 +74,11 @@ function renderBalance(type, balance) {
const ChannelsTable = () => { const ChannelsTable = () => {
const columns = [ const columns = [
// {
// title: '',
// dataIndex: 'checkbox',
// className: 'checkbox',
// },
{ {
title: 'ID', title: 'ID',
dataIndex: 'id', dataIndex: 'id',
@ -235,9 +240,11 @@ const ChannelsTable = () => {
const [channelCount, setChannelCount] = useState(pageSize); const [channelCount, setChannelCount] = useState(pageSize);
const [groupOptions, setGroupOptions] = useState([]); const [groupOptions, setGroupOptions] = useState([]);
const [showEdit, setShowEdit] = useState(false); const [showEdit, setShowEdit] = useState(false);
const [enableBatchDelete, setEnableBatchDelete] = useState(false);
const [editingChannel, setEditingChannel] = useState({ const [editingChannel, setEditingChannel] = useState({
id: undefined, id: undefined,
}); });
const [selectedChannels, setSelectedChannels] = useState([]);
const removeRecord = id => { const removeRecord = id => {
let newDataSource = [...channels]; let newDataSource = [...channels];
@ -484,6 +491,27 @@ const ChannelsTable = () => {
setUpdatingBalance(false); setUpdatingBalance(false);
}; };
const batchDeleteChannels = async () => {
if (selectedChannels.length === 0) {
showError('请先选择要删除的通道!');
return;
}
setLoading(true);
let ids = [];
selectedChannels.forEach((channel) => {
ids.push(channel.id);
});
const res = await API.post(`/api/channel/batch`, {ids: ids});
const {success, message, data} = res.data;
if (success) {
showSuccess(`已删除 ${data} 个通道!`);
await refresh();
} else {
showError(message);
}
setLoading(false);
}
const sortChannel = (key) => { const sortChannel = (key) => {
if (channels.length === 0) return; if (channels.length === 0) return;
setLoading(true); setLoading(true);
@ -557,6 +585,7 @@ const ChannelsTable = () => {
} }
}; };
return ( return (
<> <>
<EditChannel refresh={refresh} visible={showEdit} handleClose={closeEdit} editingChannel={editingChannel}/> <EditChannel refresh={refresh} visible={showEdit} handleClose={closeEdit} editingChannel={editingChannel}/>
@ -582,6 +611,7 @@ const ChannelsTable = () => {
</div> </div>
</Form> </Form>
<div style={{marginTop: 10, display: 'flex'}}> <div style={{marginTop: 10, display: 'flex'}}>
<Space>
<Space> <Space>
<Typography.Text strong>使用ID排序</Typography.Text> <Typography.Text strong>使用ID排序</Typography.Text>
<Switch checked={idSort} label='使用ID排序' uncheckedText="关" aria-label="是否用ID排序" onChange={(v) => { <Switch checked={idSort} label='使用ID排序' uncheckedText="关" aria-label="是否用ID排序" onChange={(v) => {
@ -594,6 +624,7 @@ const ChannelsTable = () => {
}) })
}}></Switch> }}></Switch>
</Space> </Space>
</Space>
</div> </div>
<Table columns={columns} dataSource={pageData} pagination={{ <Table columns={columns} dataSource={pageData} pagination={{
@ -607,7 +638,15 @@ const ChannelsTable = () => {
handlePageSizeChange(size).then() handlePageSizeChange(size).then()
}, },
onPageChange: handlePageChange, onPageChange: handlePageChange,
}} loading={loading} onRow={handleRow}/> }} loading={loading} onRow={handleRow} rowSelection={
enableBatchDelete ?
{
onChange: (selectedRowKeys, selectedRows) => {
// console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
setSelectedChannels(selectedRows);
},
} : null
}/>
<div style={{display: isMobile()?'':'flex', marginTop: isMobile()?0:-45, zIndex: 999, position: 'relative', pointerEvents: 'none'}}> <div style={{display: isMobile()?'':'flex', marginTop: isMobile()?0:-45, zIndex: 999, position: 'relative', pointerEvents: 'none'}}>
<Space style={{pointerEvents: 'auto'}}> <Space style={{pointerEvents: 'auto'}}>
<Button theme='light' type='primary' style={{marginRight: 8}} onClick={ <Button theme='light' type='primary' style={{marginRight: 8}} onClick={
@ -648,6 +687,24 @@ const ChannelsTable = () => {
{/*</div>*/} {/*</div>*/}
</div> </div>
<div style={{marginTop: 20}}>
<Space>
<Typography.Text strong>开启批量删除</Typography.Text>
<Switch label='开启批量删除' uncheckedText="关" aria-label="是否开启批量删除" onChange={(v) => {
setEnableBatchDelete(v)
}}></Switch>
<Popconfirm
title="确定是否要删除所选通道?"
content="此修改将不可逆"
okType={'danger'}
onConfirm={batchDeleteChannels}
disabled={!enableBatchDelete}
position={'top'}
>
<Button disabled={!enableBatchDelete} theme='light' type='danger' style={{marginRight: 8}}>删除所选通道</Button>
</Popconfirm>
</Space>
</div>
</> </>
); );
}; };