mirror of
https://github.com/linux-do/new-api.git
synced 2025-09-21 17:56:38 +08:00
添加批量删除渠道功能
This commit is contained in:
parent
0fdd4fc6e3
commit
e1da1e31d5
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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())
|
||||||
|
@ -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>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user