fix: bug
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 2m27s

This commit is contained in:
sexygoat
2026-04-11 16:51:54 +08:00
parent 33e15314ac
commit 4f02d6faf0
25 changed files with 387 additions and 317 deletions

View File

@@ -15,38 +15,40 @@
<!-- 详情内容 -->
<DetailPage v-if="detailData" :sections="detailSections" :data="detailData" />
<!-- 订单列表 -->
<div
v-if="detailData && detailData.items && detailData.items.length > 0"
class="order-items-section"
>
<h3 class="section-title">订单项列表</h3>
<ElTable :data="detailData.items" border style="margin-top: 10px">
<ElTableColumn prop="package_name" label="套餐名称" min-width="150" />
<ElTableColumn prop="package_type" label="套餐类型" width="120">
<template #default="{ row }">
{{
row.package_type === 'formal'
? '正式套餐'
: row.package_type === 'addon'
? '加油包'
: '-'
}}
</template>
</ElTableColumn>
<ElTableColumn prop="quantity" label="数量" width="100" />
<ElTableColumn prop="unit_price" label="单价" width="120">
<template #default="{ row }">
{{ formatCurrency(row.unit_price) }}
</template>
</ElTableColumn>
<ElTableColumn prop="amount" label="金额" width="120">
<template #default="{ row }">
{{ formatCurrency(row.amount) }}
</template>
</ElTableColumn>
</ElTable>
</div>
<!-- 订单列表 -->
<ElCard style="margin-top: 20px" shadow="never">
<div
v-if="detailData && detailData.items && detailData.items.length > 0"
class="order-items-section"
>
<h3 class="section-title">订单列表</h3>
<ElTable :data="detailData.items" border>
<ElTableColumn prop="package_name" label="套餐名称" />
<ElTableColumn prop="package_type" label="套餐类型">
<template #default="{ row }">
{{
row.package_type === 'formal'
? '正式套餐'
: row.package_type === 'addon'
? '加油包'
: '-'
}}
</template>
</ElTableColumn>
<ElTableColumn prop="quantity" label="数量" />
<ElTableColumn prop="unit_price" label="单价">
<template #default="{ row }">
{{ formatCurrency(row.unit_price) }}
</template>
</ElTableColumn>
<ElTableColumn prop="amount" label="金额">
<template #default="{ row }">
{{ formatCurrency(row.amount) }}
</template>
</ElTableColumn>
</ElTable>
</div>
</ElCard>
<!-- 加载中 -->
<div v-if="loading" class="loading-container">
@@ -286,10 +288,6 @@
}
.order-items-section {
padding-top: 20px;
margin-top: 30px;
border-top: 1px solid var(--el-border-color-lighter);
.section-title {
margin: 0 0 16px;
font-size: 16px;

View File

@@ -7,6 +7,7 @@
:items="searchFormItems"
:show-expand="false"
@reset="handleReset"
label-width="100"
@search="handleSearch"
></ArtSearchBar>
@@ -77,6 +78,7 @@
:loading="cardSearchLoading"
style="width: 100%"
clearable
@change="handleIotCardChange"
>
<ElOption
v-for="card in iotCardOptions"
@@ -104,6 +106,7 @@
:loading="deviceSearchLoading"
style="width: 100%"
clearable
@change="handleDeviceChange"
>
<ElOption
v-for="device in deviceOptions"
@@ -125,15 +128,9 @@
v-model="createForm.package_id"
:placeholder="'请选择套餐'"
filterable
remote
reserve-keyword
:remote-method="handlePackageSearch"
:loading="packageSearchLoading"
:disabled="
(!createForm.iot_card_id && !createForm.device_id) ||
(createForm.order_type === 'single_card' && !createForm.iot_card_id) ||
(createForm.order_type === 'device' && !createForm.device_id)
"
:disabled="!createForm.iot_card_id && !createForm.device_id"
clearable
style="width: 100%"
>
@@ -151,6 +148,16 @@
</div>
</ElOption>
</ElSelect>
<template v-if="noSeriesId">
<div style="color: var(--el-text-color-warning); font-size: 12px; margin-top: 4px">
该设备未关联套餐系列无法购买套餐
</div>
</template>
<template v-else-if="packagesEmptyWithSeriesId">
<div style="color: var(--el-text-color-info); font-size: 12px; margin-top: 4px">
该系列暂无可用套餐
</div>
</template>
</ElFormItem>
<ElFormItem label="支付方式" prop="payment_method">
<ElSelect
@@ -379,7 +386,8 @@
config: {
maxlength: 20,
clearable: true
}
},
labelWidth: '100'
},
{
label: '支付状态',
@@ -567,7 +575,9 @@
order_type: 'single_card' as OrderType,
package_id: undefined as number | undefined, // 前端使用单选
iot_card_id: null as number | null,
iot_card_series_id: null as number | null, // IoT卡的套餐系列ID
device_id: null as number | null,
device_series_id: null as number | null, // 设备的套餐系列ID
payment_method: 'wallet' as OrderPaymentMethod, // 默认使用钱包支付
payment_voucher_key: undefined as string | undefined // 线下支付凭证
})
@@ -577,6 +587,7 @@
// 套餐搜索相关
const packageOptions = ref<PackageResponse[]>([])
const packageSearchLoading = ref(false)
const isLoadingPackagesFromSelection = ref(false)
// IoT卡搜索相关
const iotCardOptions = ref<StandaloneIotCard[]>([])
@@ -586,46 +597,60 @@
const deviceOptions = ref<Device[]>([])
const deviceSearchLoading = ref(false)
// 搜索套餐根据套餐名称可选按series_id筛选
const searchPackages = async (query: string, seriesId?: number) => {
packageSearchLoading.value = true
try {
const res = await PackageManageService.getPackages({
package_name: query || undefined,
series_id: seriesId,
page: 1,
page_size: 20,
status: 1, // 只获取启用的套餐
shelf_status: 1 // 只获取已上架的套餐
})
if (res.code === 0) {
packageOptions.value = res.data.items || []
}
} catch (error) {
console.error('Search packages failed:', error)
// 套餐列表为空但有seriesId的提示
const packagesEmptyWithSeriesId = ref(false)
// 检查是否选择了卡/设备但没有关联套餐系列
const noSeriesId = computed(() => {
if (createForm.order_type === 'single_card' && createForm.iot_card_id) {
return !createForm.iot_card_series_id
}
if (createForm.order_type === 'device' && createForm.device_id) {
return !createForm.device_series_id
}
return false
})
// IoT卡选择变化时根据series_id加载套餐列表
const handleIotCardChange = (cardId: number | null) => {
if (!cardId) {
createForm.iot_card_series_id = null
createForm.package_id = undefined
packageOptions.value = []
packagesEmptyWithSeriesId.value = false
return
}
const selectedCard = iotCardOptions.value.find((card) => card.id === cardId)
createForm.iot_card_series_id = selectedCard?.series_id || null
createForm.package_id = undefined
packageOptions.value = []
packagesEmptyWithSeriesId.value = false
if (selectedCard?.series_id) {
loadDefaultPackages(selectedCard.series_id)
} else {
packageOptions.value = []
} finally {
packageSearchLoading.value = false
}
}
// 套餐远程搜索方法自动使用当前选中的IOT卡/设备的series_id
const handlePackageSearch = (query: string) => {
let seriesId: number | undefined
// 如果是单卡订单并且已选择IOT卡使用该卡的series_id筛选
if (createForm.order_type === 'single_card' && createForm.iot_card_id) {
const selectedCard = iotCardOptions.value.find((card) => card.id === createForm.iot_card_id)
if (selectedCard && selectedCard.series_id) {
seriesId = selectedCard.series_id
}
} else if (createForm.order_type === 'device' && createForm.device_id) {
// 如果是设备订单并且已选择设备,使用设备的series_id筛选
const selectedDevice = deviceOptions.value.find((dev) => dev.id === createForm.device_id)
if (selectedDevice && selectedDevice.series_id) {
seriesId = selectedDevice.series_id
}
// 设备选择变化时,根据series_id加载套餐列表
const handleDeviceChange = (deviceId: number | null) => {
if (!deviceId) {
createForm.device_series_id = null
createForm.package_id = undefined
packageOptions.value = []
packagesEmptyWithSeriesId.value = false
return
}
const selectedDevice = deviceOptions.value.find((dev) => dev.id === deviceId)
createForm.device_series_id = selectedDevice?.series_id || null
createForm.package_id = undefined
packageOptions.value = []
packagesEmptyWithSeriesId.value = false
if (selectedDevice?.series_id) {
loadDefaultPackages(selectedDevice.series_id)
} else {
packageOptions.value = []
}
searchPackages(query, seriesId)
}
// 搜索IoT卡根据ICCID
@@ -848,39 +873,12 @@
}
])
// 当选择IOT卡时根据series_id筛选套餐
// 当订单类型切换时,清空已选择的套餐
watch(
() => createForm.iot_card_id,
(newCardId) => {
if (newCardId && createForm.order_type === 'single_card') {
// 找到选中的IOT卡
const selectedCard = iotCardOptions.value.find((card) => card.id === newCardId)
if (selectedCard && selectedCard.series_id) {
// 根据series_id重新加载套餐列表
loadDefaultPackages(selectedCard.series_id)
} else {
// 如果没有series_id加载所有套餐
loadDefaultPackages()
}
}
}
)
// 当选择设备时根据series_id筛选套餐
watch(
() => createForm.device_id,
(newDeviceId) => {
if (newDeviceId && createForm.order_type === 'device') {
// 找到选中的设备
const selectedDevice = deviceOptions.value.find((dev) => dev.id === newDeviceId)
if (selectedDevice && selectedDevice.series_id) {
// 根据series_id重新加载套餐列表
loadDefaultPackages(selectedDevice.series_id)
} else {
// 如果没有series_id加载所有套餐
loadDefaultPackages()
}
}
() => createForm.order_type,
() => {
createForm.package_id = undefined
packageOptions.value = []
}
)
@@ -955,13 +953,14 @@
// 显示创建订单对话框
const showCreateDialog = async () => {
createDialogVisible.value = true
// 加载IoT卡和设备列表套餐列表在选择IoT卡/设备后才加载
await Promise.all([loadDefaultIotCards(), loadDefaultDevices()])
// IoT卡和设备列表在用户搜索时才加载,不在此处预加载
}
// 加载默认套餐列表可选按series_id筛选
const loadDefaultPackages = async (seriesId?: number) => {
packageSearchLoading.value = true
isLoadingPackagesFromSelection.value = true
packagesEmptyWithSeriesId.value = false
try {
const res = await PackageManageService.getPackages({
series_id: seriesId,
@@ -972,50 +971,17 @@
})
if (res.code === 0) {
packageOptions.value = res.data.items || []
// seriesId存在但返回空列表时显示提示
if (seriesId && (!res.data.items || res.data.items.length === 0)) {
packagesEmptyWithSeriesId.value = true
}
}
} catch (error) {
console.error('Load default packages failed:', error)
packageOptions.value = []
} finally {
packageSearchLoading.value = false
}
}
// 加载默认IoT卡列表
const loadDefaultIotCards = async () => {
cardSearchLoading.value = true
try {
const res = await CardService.getStandaloneIotCards({
page: 1,
page_size: 20
})
if (res.code === 0) {
iotCardOptions.value = res.data.items || []
}
} catch (error) {
console.error('Load default IoT cards failed:', error)
iotCardOptions.value = []
} finally {
cardSearchLoading.value = false
}
}
// 加载默认设备列表
const loadDefaultDevices = async () => {
deviceSearchLoading.value = true
try {
const res = await DeviceService.getDevices({
page: 1,
page_size: 20
})
if (res.code === 0) {
deviceOptions.value = res.data.items || []
}
} catch (error) {
console.error('Load default devices failed:', error)
deviceOptions.value = []
} finally {
deviceSearchLoading.value = false
isLoadingPackagesFromSelection.value = false
}
}