修复:原来的统一去了404, 现在加了403, 和部分bug
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 6m54s

This commit is contained in:
sexygoat
2026-03-03 16:26:04 +08:00
parent 7e9acda1ab
commit 237eeed87a
8 changed files with 274 additions and 91 deletions

View File

@@ -95,18 +95,6 @@
<span class="dialog-title">分配角色</span>
<div class="account-info">
<span class="account-name">{{ currentAccountName }}</span>
<ElTag v-if="currentAccountType === 1" type="danger" size="small" style="margin-left: 8px">
超级管理员不能分配角色
</ElTag>
<ElTag v-if="currentAccountType === 2" type="info" size="small" style="margin-left: 8px">
平台用户只能分配一个平台角色
</ElTag>
<ElTag v-if="currentAccountType === 3" type="warning" size="small" style="margin-left: 8px">
代理账号只能分配一个客户角色
</ElTag>
<ElTag v-if="currentAccountType === 4" type="warning" size="small" style="margin-left: 8px">
企业账号只能分配一个客户角色
</ElTag>
</div>
</div>
</template>

View File

@@ -67,6 +67,7 @@
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
@selection-change="handleSelectionChange"
@row-contextmenu="handleRowContextMenu"
>
<template #default>
<ElTableColumn type="selection" width="55" />
@@ -106,7 +107,7 @@
@selection-change="handleAvailableCardsSelectionChange"
>
<template #default>
<ElTableColumn type="selection" width="55" />
<ElTableColumn type="selection" width="55" :selectable="checkCardSelectable" />
<ElTableColumn
v-for="col in availableCardColumns"
:key="col.prop || col.type"
@@ -209,6 +210,14 @@
</div>
</template>
</ElDialog>
<!-- 表格行操作右键菜单 -->
<ArtMenuRight
ref="cardOperationMenuRef"
:menu-items="cardOperationMenuItems"
:menu-width="140"
@select="handleCardOperationMenuSelect"
/>
</ElCard>
</div>
</ArtTableFullScreen>
@@ -224,6 +233,8 @@
import { useCheckedColumns } from '@/composables/useCheckedColumns'
import { useAuth } from '@/composables/useAuth'
import { formatDateTime } from '@/utils/business/format'
import ArtMenuRight from '@/components/core/others/ArtMenuRight.vue'
import type { MenuItemType } from '@/components/core/others/ArtMenuRight.vue'
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
import { BgColorEnum } from '@/enums/appEnum'
import type {
@@ -264,6 +275,11 @@
const availableCardsLoading = ref(false)
const availableCardsList = ref<StandaloneIotCard[]>([])
const selectedAvailableCards = ref<StandaloneIotCard[]>([])
const allocatedCardIccids = ref<Set<string>>(new Set())
// 右键菜单相关
const cardOperationMenuRef = ref<InstanceType<typeof ArtMenuRight>>()
const currentOperatingCard = ref<EnterpriseCardItem | null>(null)
// 卡搜索表单初始值
const initialCardSearchState = {
@@ -433,8 +449,7 @@
{ label: '状态', prop: 'status' },
{ label: '状态名称', prop: 'status_name' },
{ label: '网络状态', prop: 'network_status' },
{ label: '网络状态名称', prop: 'network_status_name' },
{ label: '操作', prop: 'operation' }
{ label: '网络状态名称', prop: 'network_status_name' }
]
const cardList = ref<EnterpriseCardItem[]>([])
@@ -540,41 +555,6 @@
prop: 'network_status_name',
label: '网络状态名称',
width: 130
},
{
prop: 'operation',
label: '操作',
width: 100,
fixed: 'right',
formatter: (row: EnterpriseCardItem) => {
const buttons = []
if (row.network_status === 0) {
// 停机状态,显示复机按钮
if (hasAuth('enterprise_cards:resume')) {
buttons.push(
h(ArtButtonTable, {
text: '复机',
iconClass: BgColorEnum.SUCCESS,
onClick: () => handleResume(row)
})
)
}
} else {
// 开机状态,显示停机按钮
if (hasAuth('enterprise_cards:suspend')) {
buttons.push(
h(ArtButtonTable, {
text: '停机',
iconClass: BgColorEnum.ERROR,
onClick: () => handleSuspend(row)
})
)
}
}
return h('div', { style: 'display: flex; gap: 8px;' }, buttons)
}
}
])
@@ -849,10 +829,17 @@
getAvailableCardsList()
}
// 检查卡是否可选(已授权的卡不可选)
const checkCardSelectable = (row: StandaloneIotCard) => {
return !allocatedCardIccids.value.has(row.iccid)
}
// 显示授权对话框
const showAllocateDialog = () => {
allocateDialogVisible.value = true
selectedAvailableCards.value = []
// 收集已授权的卡的ICCID
allocatedCardIccids.value = new Set(cardList.value.map((card) => card.iccid))
// 重置搜索条件
Object.assign(cardSearchForm, { ...initialCardSearchState })
cardPagination.page = 1
@@ -954,6 +941,56 @@
getTableData()
}
// 右键菜单项配置
const cardOperationMenuItems = computed((): MenuItemType[] => {
const items: MenuItemType[] = []
if (!currentOperatingCard.value) return items
if (currentOperatingCard.value.network_status === 0) {
// 停机状态 - 显示复机
if (hasAuth('enterprise_cards:resume')) {
items.push({
key: 'resume',
label: '复机'
})
}
} else {
// 开机状态 - 显示停机
if (hasAuth('enterprise_cards:suspend')) {
items.push({
key: 'suspend',
label: '停机'
})
}
}
return items
})
// 处理右键菜单
const handleRowContextMenu = (row: EnterpriseCardItem, column: any, event: MouseEvent) => {
event.preventDefault()
currentOperatingCard.value = row
nextTick(() => {
cardOperationMenuRef.value?.show(event)
})
}
// 处理菜单选择
const handleCardOperationMenuSelect = (item: MenuItemType) => {
if (!currentOperatingCard.value) return
switch (item.key) {
case 'suspend':
handleSuspend(currentOperatingCard.value)
break
case 'resume':
handleResume(currentOperatingCard.value)
break
}
}
// 停机卡
const handleSuspend = (row: EnterpriseCardItem) => {
ElMessageBox.confirm('确定要停机该卡吗?', '停机卡', {

View File

@@ -747,8 +747,7 @@
// 查看客户账号
const viewCustomerAccounts = (row: EnterpriseItem) => {
router.push({
name: 'EnterpriseCustomerAccounts',
params: { id: row.id },
path: `/account-management/enterprise-customer/customer-accounts/${row.id}`,
query: { type: 'enterprise' }
})
}

View File

@@ -342,7 +342,12 @@
</ElDialog>
<!-- 套餐系列绑定结果对话框 -->
<ElDialog v-model="seriesBindingResultDialogVisible" title="设置结果" width="700px">
<ElDialog
v-model="seriesBindingResultDialogVisible"
title="设置结果"
width="700px"
@close="handleSeriesBindingResultDialogClose"
>
<ElDescriptions :column="2" border>
<ElDescriptionsItem label="成功数">
<ElTag type="success">{{ seriesBindingResult.success_count }}</ElTag>
@@ -1295,22 +1300,21 @@
try {
const res = await CardService.allocateStandaloneCards(params)
// code === 0 表示操作成功(接口调用成功),显示结果对话框
if (res.code === 0) {
allocationResult.value = res.data
resultTitle.value = '批量分配结果'
allocateDialogVisible.value = false
resultDialogVisible.value = true
// 清空选择
if (tableRef.value) {
tableRef.value.clearSelection()
}
selectedCards.value = []
// 刷新列表
getTableData()
await getTableData()
}
} catch (error) {
console.error(error)
ElMessage.error('批量分配失败,请重试')
} finally {
allocateLoading.value = false
}
@@ -1348,18 +1352,21 @@
try {
const res = await CardService.recallStandaloneCards(params)
// code === 0 表示操作成功(接口调用成功),显示结果对话框
if (res.code === 0) {
allocationResult.value = res.data
resultTitle.value = '批量回收结果'
recallDialogVisible.value = false
resultDialogVisible.value = true
// 清空选择
if (tableRef.value) {
tableRef.value.clearSelection()
}
selectedCards.value = []
// 刷新列表
getTableData()
await getTableData()
} else {
// code !== 0 才是真正的失败(接口调用失败)
ElMessage.error(res.msg || '批量回收失败,请重试')
}
} catch (error) {
console.error(error)
@@ -1424,6 +1431,12 @@
}
}
// 关闭套餐系列绑定结果对话框
const handleSeriesBindingResultDialogClose = () => {
// 刷新列表
getTableData()
}
// 执行套餐系列绑定
const handleSeriesBinding = async () => {
if (!seriesBindingFormRef.value) return
@@ -1450,13 +1463,10 @@
seriesBindingResultDialogVisible.value = true
// 清空选择
if (tableRef.value) {
tableRef.value.clearSelection()
}
selectedCards.value = []
// 刷新列表
getTableData()
// 立即刷新列表
await getTableData()
// 显示消息提示
if (res.data.fail_count === 0) {
@@ -1471,6 +1481,7 @@
}
} catch (error) {
console.error(error)
ElMessage.error('批量设置套餐系列失败,请重试')
} finally {
seriesBindingLoading.value = false
}

View File

@@ -99,14 +99,6 @@
}}</span>
<div class="account-info">
<span class="account-name">{{ currentAccountName }}</span>
<ElTag
v-if="currentAccountType === 3"
type="warning"
size="small"
style="margin-left: 8px"
>
代理账号只能分配一个客户角色
</ElTag>
</div>
</div>
</template>
@@ -776,18 +768,26 @@
border-color: var(--el-border-color);
}
.role-info {
display: flex;
align-items: center;
gap: 8px;
flex: 1;
}
:deep(.el-checkbox) {
width: 100%;
.el-checkbox__label {
width: 100%;
display: flex;
.role-info {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
flex: 1;
width: 100%;
> span:first-child {
flex: 1;
min-width: 0;
}
}
}
}
}
@@ -800,6 +800,18 @@
.role-info {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
> span:first-child {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.el-button {

View File

@@ -480,7 +480,7 @@
{
prop: 'real_data_mb',
label: '真流量',
width: 100,
width: 120,
formatter: (row: PackageResponse) => `${row.real_data_mb}MB`
},
{