feat: 套餐分配生效条件选择
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 9m23s

This commit is contained in:
luo
2026-07-22 14:21:15 +08:00
parent fbfdd01eec
commit 68aa03b538
11 changed files with 500 additions and 90 deletions

View File

@@ -170,6 +170,13 @@
{{ formatSuggestedRetailPrice(pkg.suggested_retail_price) }})
</span>
</div>
<div class="expiry-base-input-wrapper">
<ElRadioGroup v-model="pkg.expiry_base_override">
<ElRadio value="default">跟随套餐默认</ElRadio>
<ElRadio value="from_purchase">购买即生效</ElRadio>
<ElRadio value="from_realname">实名即生效</ElRadio>
</ElRadioGroup>
</div>
<ElButton type="danger" size="small" @click="removePackage(index)"
>删除</ElButton
>
@@ -178,6 +185,7 @@
<div class="form-tip"
>设置每个套餐的成本价单位不能低于成本价不能高于建议售价的50%溢价</div
>
<div class="form-tip">生效条件仅影响后续新订单不影响已购买套餐</div>
</ElFormItem>
</template>
</div>
@@ -253,7 +261,7 @@
</template>
</ElTableColumn>
<ElTableColumn label="统计范围" width="140">
<template #default="{ row }">
<template #default>
<ElTag size="small" type="warning"> 仅自己 </ElTag>
</template>
</ElTableColumn>
@@ -427,7 +435,7 @@
</template>
</ElTableColumn>
<ElTableColumn label="统计范围" width="140">
<template #default="{ row }">
<template #default>
<ElTag size="small" type="warning"> 仅自己 </ElTag>
</template>
</ElTableColumn>
@@ -546,6 +554,7 @@
import { useRouter } from 'vue-router'
import {
ShopSeriesGrantService,
ShopPackageAllocationService,
PackageSeriesService,
ShopService,
PackageManageService
@@ -558,8 +567,7 @@
ElRow,
ElCol,
ElSteps,
ElStep,
ElEmpty
ElStep
} from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
import type {
@@ -567,7 +575,8 @@
PackageSeriesResponse,
ShopResponse,
PackageResponse,
CommissionTier
CommissionTier,
PackageAllocationExpiryBaseOverride
} from '@/types/api'
import type { SearchFormItem } from '@/types'
import { useCheckedColumns } from '@/composables/useCheckedColumns'
@@ -604,8 +613,6 @@
const currentStep = ref(0) // 当前步骤0 为第一步1 为第二步
const seriesOptions = ref<PackageSeriesResponse[]>([])
const shopOptions = ref<ShopResponse[]>([])
const shopTreeData = ref<ShopResponse[]>([])
const packageOptions = ref<PackageResponse[]>([])
const selectedPackageIds = ref<number[]>([])
const searchSeriesOptions = ref<PackageSeriesResponse[]>([])
@@ -777,6 +784,7 @@
cost_price: number
original_cost_price?: number
suggested_retail_price?: number
expiry_base_override: PackageAllocationExpiryBaseOverride | 'default'
}> // 套餐配置
})
@@ -1027,39 +1035,6 @@
return actions
}
// 构建树形结构数据
const buildTreeData = (items: ShopResponse[]) => {
const map = new Map<number, ShopResponse & { children?: ShopResponse[] }>()
const tree: ShopResponse[] = []
// 先将所有项放入 map
items.forEach((item) => {
map.set(item.id, { ...item, children: [] })
})
// 构建树形结构
items.forEach((item) => {
const node = map.get(item.id)!
if (item.parent_id && map.has(item.parent_id)) {
// 有父节点,添加到父节点的 children 中
const parent = map.get(item.parent_id)!
if (!parent.children) parent.children = []
parent.children.push(node)
} else {
// 没有父节点或父节点不存在,作为根节点
tree.push(node)
}
})
return tree
}
// 店铺树节点过滤方法
const filterShopNode = (value: string, data: any) => {
if (!value) return true
return data.shop_name.toLowerCase().includes(value.toLowerCase())
}
onMounted(() => {
getTableData()
})
@@ -1170,7 +1145,8 @@
suggested_retail_price:
pkg?.suggested_retail_price !== undefined && pkg?.suggested_retail_price !== null
? pkg.suggested_retail_price / 100
: undefined
: undefined,
expiry_base_override: 'default'
})
}
})
@@ -1597,7 +1573,8 @@
pkgOption?.suggested_retail_price !== undefined &&
pkgOption?.suggested_retail_price !== null
? pkgOption.suggested_retail_price / 100
: undefined
: undefined,
expiry_base_override: pkg.expiry_base_override ?? 'default'
}
})
selectedPackageIds.value = detail.packages.map((pkg) => pkg.package_id)
@@ -1745,8 +1722,15 @@
data.force_recharge_amount = 0
}
// 可选:套餐配置(将元转换为分)
if (form.packages.length > 0) {
// 新增系列授权后,套餐通过独立分配接口创建,确保显式传递生效条件覆盖值。
const packageAllocations = form.packages.map((pkg: any) => ({
package_id: pkg.package_id,
cost_price: Math.round((pkg.cost_price ?? 0) * 100),
expiry_base_override:
pkg.expiry_base_override === 'default' ? null : pkg.expiry_base_override
}))
if (packageAllocations.length > 0) {
// 验证是否包含赠送套餐
for (const pkg of form.packages) {
const pkgInfo = packageOptions.value.find((p) => p.id === pkg.package_id)
@@ -1778,11 +1762,6 @@
return
}
}
data.packages = form.packages.map((pkg: any) => ({
package_id: pkg.package_id,
cost_price: Math.round((pkg.cost_price ?? 0) * 100) // 将元转换为分
}))
}
if (dialogType.value === 'add') {
@@ -1790,6 +1769,19 @@
data.series_id = form.series_id
data.shop_id = form.shop_id
await ShopSeriesGrantService.createShopSeriesGrant(data)
await Promise.all(
packageAllocations.map(
(pkg: {
package_id: number
cost_price: number
expiry_base_override: PackageAllocationExpiryBaseOverride | null
}) =>
ShopPackageAllocationService.createShopPackageAllocation({
shop_id: data.shop_id,
...pkg
})
)
)
ElMessage.success('新增成功')
} else {
// 编辑时调用更新接口