feat(admin): 增加履约渠道批量删除并统一分页配置

This commit is contained in:
yml2213
2026-11-02 17:31:55 +08:00
parent 735a791a2e
commit d871b93fde
14 changed files with 184 additions and 46 deletions
@@ -12,6 +12,7 @@ import {
assignChannelBySku,
assignChannelToOrderItems,
deleteChannelRule,
deleteChannelRules,
listChannelRules,
listPendingChannelGroups,
switchChannelForOrderItems,
@@ -234,6 +235,22 @@ router.delete(
}),
)
router.post(
'/fulfillment/rules/batch-delete',
requireAdminPermission('finance.config'),
createJsonHandler((req) => deleteChannelRules(Array.isArray(req.body?.ids) ? req.body.ids : []), {
successMessage: '渠道规则已批量删除',
errorMessage: '批量删除渠道规则失败',
scope: '[admin/fulfillment/rules/batch-delete]',
audit: (_req, data) => ({
action: 'fulfillment.batch_delete_rules',
targetType: 'internal_sku_channel',
targetId: '',
data: data as Record<string, unknown>,
}),
}),
)
router.get(
'/fulfillment/pipeline/status',
requireAdminPermission('finance.view'),
@@ -25,6 +25,7 @@ import {
} from './channel-types.js'
import {
deleteInternalSkuChannelById,
deleteInternalSkuChannelsByIds,
planInternalSkuChannels,
setInternalSkuPrimaryChannel,
upsertInternalSkuChannel,
@@ -1119,6 +1120,21 @@ export async function deleteChannelRule(ruleId: number): Promise<{ deleted: bool
return { deleted: await deleteInternalSkuChannelById(id) }
}
export async function deleteChannelRules(idsInput: number[]): Promise<{
deletedCount: number
deletedIds: number[]
missingIds: number[]
}> {
if (!Array.isArray(idsInput) || idsInput.length === 0) {
throw createHttpError('请选择要删除的渠道规则', {
statusCode: 400,
errorCode: 'channel_rule_ids_required',
})
}
const result = await deleteInternalSkuChannelsByIds(idsInput)
return { deletedCount: result.deletedIds.length, ...result }
}
async function loadEnabledRules(): Promise<ChannelRule[]> {
const rows = await query<ChannelRule>(
`
@@ -20,7 +20,7 @@ test(
const { closeDb, query } = await import('../../db/client.js')
const {
assignChannelByInternalSku,
deleteChannelRule,
deleteChannelRules,
ensureVoucherRuleForSku,
listChannelRules,
switchChannelForOrderItems,
@@ -171,7 +171,9 @@ test(
assert.ok(
listedRules.some((rule) => rule.id === savedRule.id && rule.match_key === voucherSku),
)
assert.equal((await deleteChannelRule(savedRule.id)).deleted, true)
const deletedRules = await deleteChannelRules([savedRule.id])
assert.equal(deletedRules.deletedCount, 1)
assert.deepEqual(deletedRules.deletedIds, [savedRule.id])
} finally {
if (orderItemIds.length > 0) {
await query(`DELETE FROM cost_exception_items WHERE order_item_id = ANY($1::bigint[])`, [
@@ -203,3 +203,21 @@ export async function deleteInternalSkuChannelById(channelId: number): Promise<b
const result = await query(`DELETE FROM internal_sku_channels WHERE id = $1`, [id])
return (result.rowCount || 0) > 0
}
export async function deleteInternalSkuChannelsByIds(idsInput: number[]): Promise<{
deletedIds: number[]
missingIds: number[]
}> {
const ids = [...new Set(idsInput.map(Number).filter((id) => Number.isInteger(id) && id > 0))]
if (ids.length === 0) return { deletedIds: [], missingIds: [] }
const result = await query<{ id: number }>(
`DELETE FROM internal_sku_channels WHERE id = ANY($1::bigint[]) RETURNING id`,
[ids],
)
const deletedIds = result.rows.map((row) => Number(row.id))
const deleted = new Set(deletedIds)
return {
deletedIds,
missingIds: ids.filter((id) => !deleted.has(id)),
}
}