fix: 取消关联,居左,店铺列表
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 2m53s
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 2m53s
This commit is contained in:
@@ -77,14 +77,13 @@
|
|||||||
<span style="font-weight: bold; color: #409eff">{{ selectedDevices.length }}</span> 台
|
<span style="font-weight: bold; color: #409eff">{{ selectedDevices.length }}</span> 台
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="店铺" prop="target_shop_id">
|
<ElFormItem label="店铺" prop="target_shop_id">
|
||||||
<ElTreeSelect
|
<ElCascader
|
||||||
v-model="allocateForm.target_shop_id"
|
v-model="allocateForm.target_shop_id"
|
||||||
:data="shopTreeData"
|
:options="shopCascadeOptions"
|
||||||
:props="{ label: 'shop_name', value: 'id', children: 'children' }"
|
:props="shopCascadeProps"
|
||||||
placeholder="请选择目标店铺"
|
placeholder="请选择目标店铺"
|
||||||
clearable
|
clearable
|
||||||
filterable
|
filterable
|
||||||
check-strictly
|
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
/>
|
/>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
@@ -222,7 +221,6 @@
|
|||||||
:loading="seriesLoading"
|
:loading="seriesLoading"
|
||||||
clearable
|
clearable
|
||||||
>
|
>
|
||||||
<ElOption label="清除关联" :value="0" />
|
|
||||||
<ElOption
|
<ElOption
|
||||||
v-for="series in packageSeriesList"
|
v-for="series in packageSeriesList"
|
||||||
:key="series.id"
|
:key="series.id"
|
||||||
@@ -572,15 +570,7 @@
|
|||||||
PackageSeriesService,
|
PackageSeriesService,
|
||||||
AssetService
|
AssetService
|
||||||
} from '@/api/modules'
|
} from '@/api/modules'
|
||||||
import {
|
import { ElMessage, ElMessageBox, ElTag, ElIcon, ElRadioGroup, ElRadio } from 'element-plus'
|
||||||
ElMessage,
|
|
||||||
ElMessageBox,
|
|
||||||
ElTag,
|
|
||||||
ElIcon,
|
|
||||||
ElTreeSelect,
|
|
||||||
ElRadioGroup,
|
|
||||||
ElRadio
|
|
||||||
} from 'element-plus'
|
|
||||||
import { Loading } from '@element-plus/icons-vue'
|
import { Loading } from '@element-plus/icons-vue'
|
||||||
import type { FormInstance, FormRules } from 'element-plus'
|
import type { FormInstance, FormRules } from 'element-plus'
|
||||||
import type {
|
import type {
|
||||||
@@ -610,7 +600,35 @@
|
|||||||
const allocateDialogVisible = ref(false)
|
const allocateDialogVisible = ref(false)
|
||||||
const recallDialogVisible = ref(false)
|
const recallDialogVisible = ref(false)
|
||||||
const selectedDevices = ref<Device[]>([])
|
const selectedDevices = ref<Device[]>([])
|
||||||
const shopTreeData = ref<any[]>([])
|
const shopCascadeOptions = ref<any[]>([])
|
||||||
|
const shopCascadeProps = {
|
||||||
|
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 })
|
||||||
|
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 allocateResult = ref<AllocateDevicesResponse | null>(null)
|
||||||
const recallResult = ref<RecallDevicesResponse | null>(null)
|
const recallResult = ref<RecallDevicesResponse | null>(null)
|
||||||
|
|
||||||
@@ -1146,7 +1164,6 @@
|
|||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getTableData()
|
getTableData()
|
||||||
loadShopTree()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// 当页面被 keep-alive 激活时自动刷新数据
|
// 当页面被 keep-alive 激活时自动刷新数据
|
||||||
@@ -1154,49 +1171,6 @@
|
|||||||
getTableData()
|
getTableData()
|
||||||
})
|
})
|
||||||
|
|
||||||
// 加载店铺树形数据
|
|
||||||
const loadShopTree = async () => {
|
|
||||||
try {
|
|
||||||
const res = await ShopService.getShops({
|
|
||||||
page: 1,
|
|
||||||
page_size: 9999, // 获取所有数据用于构建树形结构
|
|
||||||
status: 1 // 只获取启用的店铺
|
|
||||||
})
|
|
||||||
if (res.code === 0) {
|
|
||||||
shopTreeData.value = buildShopTree(res.data.items || [])
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取店铺列表失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建店铺树形结构
|
|
||||||
const buildShopTree = (shops: any[]) => {
|
|
||||||
const map = new Map<number, any>()
|
|
||||||
const tree: any[] = []
|
|
||||||
|
|
||||||
// 先将所有项放入 map
|
|
||||||
shops.forEach((shop) => {
|
|
||||||
map.set(shop.id, { ...shop, children: [] })
|
|
||||||
})
|
|
||||||
|
|
||||||
// 构建树形结构
|
|
||||||
shops.forEach((shop) => {
|
|
||||||
const node = map.get(shop.id)!
|
|
||||||
if (shop.parent_id && map.has(shop.parent_id)) {
|
|
||||||
// 有父节点,添加到父节点的 children 中
|
|
||||||
const parent = map.get(shop.parent_id)!
|
|
||||||
if (!parent.children) parent.children = []
|
|
||||||
parent.children.push(node)
|
|
||||||
} else {
|
|
||||||
// 没有父节点或父节点不存在,作为根节点
|
|
||||||
tree.push(node)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return tree
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取设备列表
|
// 获取设备列表
|
||||||
const getTableData = async () => {
|
const getTableData = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@@ -1278,7 +1252,43 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
// 用户取消删除
|
// 用户取消
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除设备套餐系列绑定
|
||||||
|
const handleClearDeviceSeries = async (deviceNo: string) => {
|
||||||
|
const device = deviceList.value.find((d) => d.virtual_no === deviceNo)
|
||||||
|
if (!device) {
|
||||||
|
ElMessage.error('未找到该设备')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ElMessageBox.confirm(`确定要清除设备 ${deviceNo} 的套餐系列关联吗?`, '确认清除', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
.then(async () => {
|
||||||
|
try {
|
||||||
|
const res = await DeviceService.batchSetDeviceSeriesBinding({
|
||||||
|
device_ids: [device.id],
|
||||||
|
series_id: 0
|
||||||
|
})
|
||||||
|
if (res.code === 0) {
|
||||||
|
if (res.data.fail_count === 0) {
|
||||||
|
ElMessage.success('清除关联成功')
|
||||||
|
} else {
|
||||||
|
ElMessage.warning(`部分失败:${res.data.failed_items?.[0]?.reason || '未知原因'}`)
|
||||||
|
}
|
||||||
|
await getTableData()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('清除关联失败:', error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// 用户取消
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1534,6 +1544,9 @@
|
|||||||
case 'delete':
|
case 'delete':
|
||||||
await handleDeleteDeviceByNo(deviceNo)
|
await handleDeleteDeviceByNo(deviceNo)
|
||||||
break
|
break
|
||||||
|
case 'clear-series':
|
||||||
|
await handleClearDeviceSeries(deviceNo)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1794,6 +1807,14 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasAuth('device:clear_series')) {
|
||||||
|
moreActions.push({
|
||||||
|
label: '清除关联',
|
||||||
|
handler: () => handleDeviceOperation('clear-series', row.virtual_no, row),
|
||||||
|
type: 'primary'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// if (hasAuth('device:manual_deactivate')) {
|
// if (hasAuth('device:manual_deactivate')) {
|
||||||
// moreActions.push({
|
// moreActions.push({
|
||||||
// label: '手动停用',
|
// label: '手动停用',
|
||||||
|
|||||||
@@ -94,24 +94,15 @@
|
|||||||
label-width="120px"
|
label-width="120px"
|
||||||
>
|
>
|
||||||
<ElFormItem label="店铺" prop="to_shop_id">
|
<ElFormItem label="店铺" prop="to_shop_id">
|
||||||
<ElSelect
|
<ElCascader
|
||||||
v-model="allocateForm.to_shop_id"
|
v-model="allocateForm.to_shop_id"
|
||||||
placeholder="请选择或搜索目标店铺"
|
:options="shopCascadeOptions"
|
||||||
filterable
|
:props="shopCascadeProps"
|
||||||
remote
|
placeholder="请选择目标店铺"
|
||||||
reserve-keyword
|
|
||||||
:remote-method="searchTargetShops"
|
|
||||||
:loading="targetShopLoading"
|
|
||||||
clearable
|
clearable
|
||||||
|
filterable
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
>
|
/>
|
||||||
<ElOption
|
|
||||||
v-for="shop in targetShopList"
|
|
||||||
:key="shop.id"
|
|
||||||
:label="shop.shop_name"
|
|
||||||
:value="shop.id"
|
|
||||||
/>
|
|
||||||
</ElSelect>
|
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="选卡方式" prop="selection_type">
|
<ElFormItem label="选卡方式" prop="selection_type">
|
||||||
<ElRadioGroup v-model="allocateForm.selection_type">
|
<ElRadioGroup v-model="allocateForm.selection_type">
|
||||||
@@ -342,7 +333,6 @@
|
|||||||
:loading="seriesLoading"
|
:loading="seriesLoading"
|
||||||
clearable
|
clearable
|
||||||
>
|
>
|
||||||
<ElOption label="清除关联" :value="0" />
|
|
||||||
<ElOption
|
<ElOption
|
||||||
v-for="series in packageSeriesList"
|
v-for="series in packageSeriesList"
|
||||||
:key="series.id"
|
:key="series.id"
|
||||||
@@ -650,8 +640,35 @@
|
|||||||
const moreMenuRef = ref<InstanceType<typeof ArtMenuRight>>()
|
const moreMenuRef = ref<InstanceType<typeof ArtMenuRight>>()
|
||||||
|
|
||||||
// 店铺相关
|
// 店铺相关
|
||||||
const targetShopLoading = ref(false)
|
const shopCascadeOptions = ref<any[]>([])
|
||||||
const targetShopList = ref<any[]>([])
|
const shopCascadeProps = {
|
||||||
|
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 })
|
||||||
|
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 initialSearchState: {
|
const initialSearchState: {
|
||||||
@@ -1213,33 +1230,6 @@
|
|||||||
selectedCards.value = selection
|
selectedCards.value = selection
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载目标店铺列表
|
|
||||||
const loadTargetShops = async (shopName?: string) => {
|
|
||||||
targetShopLoading.value = true
|
|
||||||
try {
|
|
||||||
const params: any = {
|
|
||||||
page: 1,
|
|
||||||
page_size: 20
|
|
||||||
}
|
|
||||||
if (shopName) {
|
|
||||||
params.shop_name = shopName
|
|
||||||
}
|
|
||||||
const res = await ShopService.getShops(params)
|
|
||||||
if (res.code === 0) {
|
|
||||||
targetShopList.value = res.data.items || []
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取目标店铺列表失败:', error)
|
|
||||||
} finally {
|
|
||||||
targetShopLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 搜索目标店铺
|
|
||||||
const searchTargetShops = async (query: string) => {
|
|
||||||
await loadTargetShops(query || undefined)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示批量分配对话框
|
// 显示批量分配对话框
|
||||||
const showAllocateDialog = () => {
|
const showAllocateDialog = () => {
|
||||||
if (selectedCards.value.length === 0) {
|
if (selectedCards.value.length === 0) {
|
||||||
@@ -1258,8 +1248,6 @@
|
|||||||
batch_no: '',
|
batch_no: '',
|
||||||
remark: ''
|
remark: ''
|
||||||
})
|
})
|
||||||
// 加载默认店铺列表
|
|
||||||
loadTargetShops()
|
|
||||||
if (allocateFormRef.value) {
|
if (allocateFormRef.value) {
|
||||||
allocateFormRef.value.resetFields()
|
allocateFormRef.value.resetFields()
|
||||||
}
|
}
|
||||||
@@ -1536,6 +1524,13 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasAuth('iot_card:clear_series')) {
|
||||||
|
items.push({
|
||||||
|
key: 'clearSeries',
|
||||||
|
label: '清除关联'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return items
|
return items
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1565,9 +1560,52 @@
|
|||||||
case 'changePackage':
|
case 'changePackage':
|
||||||
changePackage()
|
changePackage()
|
||||||
break
|
break
|
||||||
|
case 'clearSeries':
|
||||||
|
handleClearCardSeries()
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 清除卡套餐系列绑定
|
||||||
|
const handleClearCardSeries = async () => {
|
||||||
|
if (selectedCards.value.length === 0) {
|
||||||
|
ElMessage.warning('请先选择要清除关联的卡')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
`确定要清除所选 ${selectedCards.value.length} 张卡的套餐系列关联吗?`,
|
||||||
|
'确认清除',
|
||||||
|
{
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(async () => {
|
||||||
|
try {
|
||||||
|
const res = await CardService.batchSetCardSeriesBinding({
|
||||||
|
iccids: selectedCards.value.map((card) => card.iccid),
|
||||||
|
series_id: 0
|
||||||
|
})
|
||||||
|
if (res.code === 0) {
|
||||||
|
if (res.data.fail_count === 0) {
|
||||||
|
ElMessage.success('清除关联成功')
|
||||||
|
} else {
|
||||||
|
ElMessage.warning(`部分失败:${res.data.failed_items?.[0]?.reason || '未知原因'}`)
|
||||||
|
}
|
||||||
|
selectedCards.value = []
|
||||||
|
await getTableData()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('清除关联失败:', error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// 用户取消
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 网卡分销 - 正在开发中
|
// 网卡分销 - 正在开发中
|
||||||
const cardDistribution = () => {
|
const cardDistribution = () => {
|
||||||
ElMessage.info('功能正在开发中')
|
ElMessage.info('功能正在开发中')
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
:close-on-click-modal="false"
|
:close-on-click-modal="false"
|
||||||
@closed="handleDialogClosed"
|
@closed="handleDialogClosed"
|
||||||
>
|
>
|
||||||
<ElForm ref="formRef" :model="form" :rules="rules" label-width="165px">
|
<ElForm ref="formRef" :model="form" :rules="rules" label-width="120px">
|
||||||
<ElRow :gutter="20">
|
<ElRow :gutter="20">
|
||||||
<ElCol :span="24">
|
<ElCol :span="24">
|
||||||
<ElFormItem label="套餐编码" prop="package_code">
|
<ElFormItem label="套餐编码" prop="package_code">
|
||||||
|
|||||||
Reference in New Issue
Block a user