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