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

This commit is contained in:
sexygoat
2026-05-11 15:51:50 +08:00
parent 766497dc31
commit 1990a3ccba
40 changed files with 832 additions and 127 deletions

View File

@@ -36,7 +36,6 @@
<ElButton
type="info"
@click="handleBatchSetSeries"
:disabled="!selectedDevices.length"
v-permission="'device:batch_set_series'"
>
批量设置套餐系列
@@ -200,6 +199,7 @@
v-model="seriesBindingDialogVisible"
title="批量设置设备套餐系列绑定"
width="600px"
@close="handleCloseSeriesBindingDialog"
>
<ElForm
ref="seriesBindingFormRef"
@@ -210,7 +210,167 @@
<ElFormItem label="已选设备数">
<span style="font-weight: bold; color: #409eff">{{ selectedDevices.length }}</span>
</ElFormItem>
<ElFormItem label="套餐系列" prop="series_id">
<ElFormItem label="选设备方式" prop="selection_type">
<ElRadioGroup v-model="seriesBindingForm.selection_type">
<ElRadio label="list">设备ID列表</ElRadio>
<ElRadio label="range">设备号范围</ElRadio>
<ElRadio label="filter">筛选条件</ElRadio>
</ElRadioGroup>
</ElFormItem>
<ElFormItem
v-if="seriesBindingForm.selection_type === DeviceSelectionType.LIST"
label="设备列表"
>
<div>已选择 {{ selectedDevices.length }} 台设备</div>
</ElFormItem>
<ElFormItem
v-if="seriesBindingForm.selection_type === DeviceSelectionType.RANGE"
label="起始设备号"
prop="virtual_no_start"
>
<ElInput
v-model="seriesBindingForm.virtual_no_start"
placeholder="请输入起始设备号"
/>
</ElFormItem>
<ElFormItem
v-if="seriesBindingForm.selection_type === DeviceSelectionType.RANGE"
label="结束设备号"
prop="virtual_no_end"
>
<ElInput v-model="seriesBindingForm.virtual_no_end" placeholder="请输入结束设备号" />
</ElFormItem>
<ElFormItem
v-if="seriesBindingForm.selection_type === DeviceSelectionType.FILTER"
label="设备号"
>
<ElInput
v-model="seriesBindingForm.virtual_no"
placeholder="请输入设备号"
clearable
/>
</ElFormItem>
<ElFormItem
v-if="seriesBindingForm.selection_type === DeviceSelectionType.FILTER"
label="设备名称"
>
<ElInput
v-model="seriesBindingForm.device_name"
placeholder="请输入设备名称"
clearable
/>
</ElFormItem>
<ElFormItem
v-if="seriesBindingForm.selection_type === DeviceSelectionType.FILTER"
label="设备类型"
>
<ElInput
v-model="seriesBindingForm.device_type"
placeholder="请输入设备类型"
clearable
/>
</ElFormItem>
<ElFormItem
v-if="seriesBindingForm.selection_type === DeviceSelectionType.FILTER"
label="制造商"
>
<ElInput
v-model="seriesBindingForm.manufacturer"
placeholder="请输入制造商"
clearable
/>
</ElFormItem>
<ElFormItem
v-if="seriesBindingForm.selection_type === DeviceSelectionType.FILTER"
label="状态"
>
<ElSelect
v-model="seriesBindingForm.status"
placeholder="请选择状态"
clearable
style="width: 100%"
>
<ElOption label="在库" :value="1" />
<ElOption label="已分销" :value="2" />
<ElOption label="已激活" :value="3" />
<ElOption label="已停用" :value="4" />
</ElSelect>
</ElFormItem>
<ElFormItem
v-if="seriesBindingForm.selection_type === DeviceSelectionType.FILTER"
label="批次号"
>
<ElSelect
v-model="seriesBindingForm.batch_no"
placeholder="请选择或搜索批次号"
clearable
filterable
remote
:remote-method="handleSearchBatchNo"
style="width: 100%"
>
<ElOption
v-for="item in searchBatchNoOptions"
:key="item.id"
:label="item.batch_no"
:value="item.batch_no"
/>
</ElSelect>
</ElFormItem>
<ElFormItem
v-if="seriesBindingForm.selection_type === DeviceSelectionType.FILTER"
label="店铺名称"
>
<ElCascader
v-model="seriesBindingForm.shop_id_path"
:options="seriesBindingShopCascadeOptions"
:props="seriesBindingShopCascadeProps"
placeholder="请选择店铺名称"
clearable
filterable
style="width: 100%"
/>
</ElFormItem>
<ElFormItem
v-if="seriesBindingForm.selection_type === DeviceSelectionType.FILTER"
label="当前套餐系列"
>
<ElSelect
v-model="seriesBindingForm.filter_series_id"
placeholder="请选择或搜索当前套餐系列"
clearable
filterable
remote
:remote-method="searchSeries"
style="width: 100%"
>
<ElOption
v-for="series in searchSeriesOptions"
:key="series.id"
:label="series.series_name"
:value="series.id"
/>
</ElSelect>
</ElFormItem>
<ElFormItem
v-if="seriesBindingForm.selection_type === DeviceSelectionType.FILTER"
label="创建设备时间"
>
<ElDatePicker
v-model="seriesBindingForm.created_at_range"
type="daterange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
value-format="YYYY-MM-DD"
style="width: 100%"
/>
</ElFormItem>
<ElFormItem label="目标套餐系列" prop="series_id">
<ElSelect
v-model="seriesBindingForm.series_id"
placeholder="请选择或搜索套餐系列"
@@ -517,6 +677,7 @@
AssetService,
CarrierService
} from '@/api/modules'
import { DeviceSelectionType } from '@/types/api'
import { ElMessage, ElMessageBox, ElTag, ElIcon, ElRadioGroup, ElRadio } from 'element-plus'
import { Loading } from '@element-plus/icons-vue'
import type { FormInstance, FormRules } from 'element-plus'
@@ -527,6 +688,7 @@
DeviceStatus,
AllocateDevicesResponse,
RecallDevicesResponse,
BatchSetDeviceSeriesBindingRequest,
BatchSetDeviceSeriesBindingResponse
} from '@/types/api'
import type { SearchFormItem } from '@/types'
@@ -593,6 +755,38 @@
label: 'label',
children: 'children'
}
const seriesBindingShopCascadeOptions = ref<any[]>([])
const seriesBindingShopCascadeProps = {
lazy: true,
checkStrictly: true,
lazyLoad: async (node: any, resolve: any) => {
const { level, value } = node
const parentId = level === 0 ? undefined : value
try {
const res = await ShopService.getShopsCascade({
parent_id: parentId,
exclude_self: true
})
if (res.code === 0) {
const nodes = (res.data || []).map((item: any) => ({
value: item.id,
label: item.shop_name,
leaf: !item.has_children
}))
resolve(nodes)
} else {
resolve([])
}
} catch (error) {
console.error('加载批量设置套餐系列店铺级联数据失败:', error)
resolve([])
}
},
value: 'value',
label: 'label',
children: 'children'
}
const allocateResult = ref<AllocateDevicesResponse | null>(null)
const recallResult = ref<RecallDevicesResponse | null>(null)
@@ -602,11 +796,53 @@
const seriesBindingFormRef = ref<FormInstance>()
const seriesLoading = ref(false)
const packageSeriesList = ref<PackageSeriesResponse[]>([])
const seriesBindingForm = reactive({
series_id: undefined as number | undefined
const createInitialSeriesBindingState = () => ({
selection_type: DeviceSelectionType.LIST,
series_id: undefined as number | undefined,
virtual_no_start: '',
virtual_no_end: '',
virtual_no: '',
device_name: '',
device_type: '',
manufacturer: '',
batch_no: '',
status: undefined as DeviceStatus | undefined,
shop_id_path: undefined as number[] | undefined,
filter_series_id: undefined as number | undefined,
created_at_range: [] as string[],
created_at_start: '',
created_at_end: ''
})
const seriesBindingForm = reactive(createInitialSeriesBindingState())
const seriesBindingRules = reactive<FormRules>({
series_id: [{ required: true, message: '请选择套餐系列', trigger: 'change' }]
selection_type: [{ required: true, message: '请选择选设备方式', trigger: 'change' }],
series_id: [{ required: true, message: '请选择套餐系列', trigger: 'change' }],
virtual_no_start: [
{
required: true,
validator: (_rule, value, callback) => {
if (seriesBindingForm.selection_type === DeviceSelectionType.RANGE && !value) {
callback(new Error('请输入起始设备号'))
} else {
callback()
}
},
trigger: 'blur'
}
],
virtual_no_end: [
{
required: true,
validator: (_rule, value, callback) => {
if (seriesBindingForm.selection_type === DeviceSelectionType.RANGE && !value) {
callback(new Error('请输入结束设备号'))
} else {
callback()
}
},
trigger: 'blur'
}
]
})
const seriesBindingResult = ref<BatchSetDeviceSeriesBindingResponse | null>(null)
@@ -1427,6 +1663,7 @@
.then(async () => {
try {
const res = await DeviceService.batchSetDeviceSeriesBinding({
selection_type: DeviceSelectionType.LIST,
device_ids: [device.id],
series_id: 0
})
@@ -1558,14 +1795,18 @@
// 批量设置套餐系列
const handleBatchSetSeries = async () => {
if (selectedDevices.value.length === 0) {
ElMessage.warning('请先选择要设置的设备')
return
}
seriesBindingForm.series_id = undefined
seriesBindingResult.value = null
await loadPackageSeriesList()
Object.assign(seriesBindingForm, createInitialSeriesBindingState(), {
selection_type:
selectedDevices.value.length > 0 ? DeviceSelectionType.LIST : DeviceSelectionType.FILTER
})
await Promise.all([
loadPackageSeriesList(),
loadSearchBatchNoOptions(),
loadSeriesBindingShopCascadeOptions()
])
seriesBindingDialogVisible.value = true
seriesBindingFormRef.value?.clearValidate()
}
// 加载套餐系列列表支持名称搜索默认20条
@@ -1596,6 +1837,66 @@
await loadPackageSeriesList(query || undefined)
}
const loadSeriesBindingShopCascadeOptions = async () => {
try {
const res = await ShopService.getShopsCascade({
parent_id: undefined,
exclude_self: true
})
if (res.code === 0) {
seriesBindingShopCascadeOptions.value = (res.data || []).map((item: any) => ({
value: item.id,
label: item.shop_name,
leaf: !item.has_children
}))
}
} catch (error) {
console.error('加载批量设置套餐系列根级店铺失败:', error)
}
}
const buildSeriesBindingRequest = (): BatchSetDeviceSeriesBindingRequest | null => {
const request: BatchSetDeviceSeriesBindingRequest = {
selection_type: seriesBindingForm.selection_type,
series_id: seriesBindingForm.series_id!
}
if (seriesBindingForm.selection_type === DeviceSelectionType.LIST) {
const deviceIds = selectedDevices.value.map((device) => device.id)
if (deviceIds.length === 0) {
ElMessage.warning('列表模式下请先选择要设置的设备')
return null
}
request.device_ids = deviceIds
return request
}
if (seriesBindingForm.selection_type === DeviceSelectionType.RANGE) {
request.virtual_no_start = seriesBindingForm.virtual_no_start
request.virtual_no_end = seriesBindingForm.virtual_no_end
return request
}
if (seriesBindingForm.virtual_no) request.virtual_no = seriesBindingForm.virtual_no
if (seriesBindingForm.device_name) request.device_name = seriesBindingForm.device_name
if (seriesBindingForm.device_type) request.device_type = seriesBindingForm.device_type
if (seriesBindingForm.manufacturer) request.manufacturer = seriesBindingForm.manufacturer
if (seriesBindingForm.batch_no) request.batch_no = seriesBindingForm.batch_no
if (seriesBindingForm.status !== undefined) request.status = seriesBindingForm.status
if (seriesBindingForm.shop_id_path?.length) {
request.shop_id = seriesBindingForm.shop_id_path[seriesBindingForm.shop_id_path.length - 1]
}
if (seriesBindingForm.filter_series_id !== undefined) {
request.filter_series_id = seriesBindingForm.filter_series_id
}
if (seriesBindingForm.created_at_range.length === 2) {
request.created_at_start = seriesBindingForm.created_at_range[0]
request.created_at_end = seriesBindingForm.created_at_range[1]
}
return request
}
// 确认设置套餐系列绑定
const handleConfirmSeriesBinding = async () => {
if (!seriesBindingFormRef.value) return
@@ -1604,9 +1905,9 @@
if (valid) {
seriesBindingLoading.value = true
try {
const data = {
device_ids: selectedDevices.value.map((d) => d.id),
series_id: seriesBindingForm.series_id!
const data = buildSeriesBindingRequest()
if (!data) {
return
}
const res = await DeviceService.batchSetDeviceSeriesBinding(data)
if (res.code === 0) {
@@ -1634,6 +1935,7 @@
const handleCloseSeriesBindingDialog = () => {
seriesBindingDialogVisible.value = false
seriesBindingResult.value = null
Object.assign(seriesBindingForm, createInitialSeriesBindingState())
if (seriesBindingFormRef.value) {
seriesBindingFormRef.value.resetFields()
}