This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user