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

This commit is contained in:
sexygoat
2026-02-27 17:40:02 +08:00
parent f1cb1e53c8
commit 4470a4ef04
17 changed files with 908 additions and 544 deletions

View File

@@ -30,12 +30,21 @@
:marginTop="10"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
@row-contextmenu="handleRowContextMenu"
>
<template #default>
<ElTableColumn v-for="col in columns" :key="col.prop || col.type" v-bind="col" />
</template>
</ArtTable>
<!-- 右键菜单 -->
<ArtMenuRight
ref="contextMenuRef"
:menu-items="contextMenuItems"
:menu-width="120"
@select="handleContextMenuSelect"
/>
<!-- 授权详情对话框 -->
<ElDialog v-model="detailDialogVisible" title="授权详情" width="700px">
<ElDescriptions v-if="currentRecord" :column="2" border>
@@ -119,6 +128,8 @@
import { useAuth } from '@/composables/useAuth'
import { formatDateTime } from '@/utils/business/format'
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
import ArtMenuRight from '@/components/core/others/ArtMenuRight.vue'
import type { MenuItemType } from '@/components/core/others/ArtMenuRight.vue'
import type {
AuthorizationItem,
AuthorizationStatus,
@@ -138,6 +149,8 @@
const remarkFormRef = ref<FormInstance>()
const currentRecordId = ref<number>(0)
const currentRecord = ref<AuthorizationItem | null>(null)
const contextMenuRef = ref<InstanceType<typeof ArtMenuRight>>()
const currentRow = ref<AuthorizationItem | null>(null)
// 搜索表单初始值
const initialSearchState = {
@@ -227,8 +240,7 @@
{ label: '授权人类型', prop: 'authorizer_type' },
{ label: '授权时间', prop: 'authorized_at' },
{ label: '状态', prop: 'status' },
{ label: '备注', prop: 'remark' },
{ label: '操作', prop: 'operation' }
{ label: '备注', prop: 'remark' }
]
const authorizationList = ref<AuthorizationItem[]>([])
@@ -306,33 +318,6 @@
minWidth: 150,
showOverflowTooltip: true,
formatter: (row: AuthorizationItem) => row.remark || '-'
},
{
prop: 'operation',
label: '操作',
width: 150,
fixed: 'right',
formatter: (row: AuthorizationItem) => {
const buttons = []
buttons.push(
h(ArtButtonTable, {
text: '详情',
onClick: () => viewDetail(row)
})
)
if (hasAuth('authorization_records:update_remark')) {
buttons.push(
h(ArtButtonTable, {
text: '编辑',
onClick: () => showRemarkDialog(row)
})
)
}
return h('div', { style: 'display: flex; gap: 8px;' }, buttons)
}
}
])
@@ -443,6 +428,41 @@
}
})
}
// 右键菜单项配置
const contextMenuItems = computed((): MenuItemType[] => {
const items: MenuItemType[] = []
items.push({ key: 'detail', label: '详情' })
if (hasAuth('authorization_records:update_remark')) {
items.push({ key: 'edit', label: '编辑' })
}
return items
})
// 处理表格行右键菜单
const handleRowContextMenu = (row: AuthorizationItem, column: any, event: MouseEvent) => {
event.preventDefault()
event.stopPropagation()
currentRow.value = row
contextMenuRef.value?.show(event)
}
// 处理右键菜单选择
const handleContextMenuSelect = (item: MenuItemType) => {
if (!currentRow.value) return
switch (item.key) {
case 'detail':
viewDetail(currentRow.value)
break
case 'edit':
showRemarkDialog(currentRow.value)
break
}
}
</script>
<style lang="scss" scoped>

View File

@@ -41,11 +41,20 @@
:marginTop="10"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
@row-contextmenu="handleRowContextMenu"
>
<template #default>
<ElTableColumn v-for="col in columns" :key="col.prop || col.type" v-bind="col" />
</template>
</ArtTable>
<!-- 右键菜单 -->
<ArtMenuRight
ref="contextMenuRef"
:menu-items="contextMenuItems"
:menu-width="120"
@select="handleContextMenuSelect"
/>
</ElCard>
</div>
@@ -223,6 +232,8 @@
import { useAuth } from '@/composables/useAuth'
import { formatDateTime } from '@/utils/business/format'
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
import ArtMenuRight from '@/components/core/others/ArtMenuRight.vue'
import type { MenuItemType } from '@/components/core/others/ArtMenuRight.vue'
import { StorageService } from '@/api/modules/storage'
import type { DeviceImportTask, DeviceImportTaskStatus } from '@/types/api/device'
@@ -236,6 +247,8 @@
const uploading = ref(false)
const importDialogVisible = ref(false)
const detailDialogVisible = ref(false)
const contextMenuRef = ref<InstanceType<typeof ArtMenuRight>>()
const currentRow = ref<DeviceImportTask | null>(null)
// 搜索表单初始值
const initialSearchState = {
@@ -306,8 +319,7 @@
{ label: '开始时间', prop: 'started_at' },
{ label: '完成时间', prop: 'completed_at' },
{ label: '错误信息', prop: 'error_message' },
{ label: '创建时间', prop: 'created_at' },
{ label: '操作', prop: 'operation' }
{ label: '创建时间', prop: 'created_at' }
]
const taskList = ref<DeviceImportTask[]>([])
@@ -421,36 +433,6 @@
label: '创建时间',
width: 180,
formatter: (row: DeviceImportTask) => formatDateTime(row.created_at)
},
{
prop: 'operation',
label: '操作',
width: 180,
fixed: 'right',
formatter: (row: DeviceImportTask) => {
const buttons = []
// 显示"查看详情"按钮
buttons.push(
h(ArtButtonTable, {
text: '详情',
onClick: () => viewDetail(row)
})
)
// 如果有失败数据,显示"失败数据"按钮
if (row.fail_count > 0) {
buttons.push(
h(ArtButtonTable, {
text: '失败数据',
type: 'danger',
onClick: () => downloadFailDataByRow(row)
})
)
}
return h('div', { style: 'display: flex; gap: 8px;' }, buttons)
}
}
])
@@ -831,6 +813,43 @@
ElMessage.success('失败数据下载成功')
}
// 右键菜单项配置
const contextMenuItems = computed((): MenuItemType[] => {
if (!currentRow.value) return []
const items: MenuItemType[] = []
items.push({ key: 'detail', label: '详情' })
if (currentRow.value.fail_count > 0) {
items.push({ key: 'failData', label: '失败数据' })
}
return items
})
// 处理表格行右键菜单
const handleRowContextMenu = (row: DeviceImportTask, column: any, event: MouseEvent) => {
event.preventDefault()
event.stopPropagation()
currentRow.value = row
contextMenuRef.value?.show(event)
}
// 处理右键菜单选择
const handleContextMenuSelect = (item: MenuItemType) => {
if (!currentRow.value) return
switch (item.key) {
case 'detail':
viewDetail(currentRow.value)
break
case 'failData':
downloadFailDataByRow(currentRow.value)
break
}
}
</script>
<style lang="scss" scoped>

View File

@@ -397,18 +397,14 @@
<ElDescriptionsItem label="卡业务类型">{{
getCardCategoryText(currentCardDetail.card_category)
}}</ElDescriptionsItem>
<ElDescriptionsItem label="成本价">{{
formatCardPrice(currentCardDetail.cost_price)
}}</ElDescriptionsItem>
<ElDescriptionsItem label="分销价">{{
formatCardPrice(currentCardDetail.distribute_price)
}}</ElDescriptionsItem>
<ElDescriptionsItem label="状态">
<ElTag :type="getCardDetailStatusTagType(currentCardDetail.status)">
{{ getCardDetailStatusText(currentCardDetail.status) }}
</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="套餐系列">{{
currentCardDetail.series_name || '--'
}}</ElDescriptionsItem>
<ElDescriptionsItem label="激活状态">
<ElTag :type="currentCardDetail.activation_status === 1 ? 'success' : 'info'">
{{ currentCardDetail.activation_status === 1 ? '已激活' : '未激活' }}
@@ -863,8 +859,6 @@
{ label: '运营商', prop: 'carrier_name' },
{ label: '店铺名称', prop: 'shop_name' },
{ label: '套餐系列', prop: 'series_name' },
{ label: '成本价', prop: 'cost_price' },
{ label: '分销价', prop: 'distribute_price' },
{ label: '状态', prop: 'status' },
{ label: '激活状态', prop: 'activation_status' },
{ label: '网络状态', prop: 'network_status' },
@@ -1020,18 +1014,6 @@
width: 150,
formatter: (row: StandaloneIotCard) => row.series_name || '-'
},
{
prop: 'cost_price',
label: '成本价',
width: 100,
formatter: (row: StandaloneIotCard) => `¥${(row.cost_price / 100).toFixed(2)}`
},
{
prop: 'distribute_price',
label: '分销价',
width: 100,
formatter: (row: StandaloneIotCard) => `¥${(row.distribute_price / 100).toFixed(2)}`
},
{
prop: 'status',
label: '状态',

View File

@@ -41,11 +41,20 @@
:marginTop="10"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
@row-contextmenu="handleRowContextMenu"
>
<template #default>
<ElTableColumn v-for="col in columns" :key="col.prop || col.type" v-bind="col" />
</template>
</ArtTable>
<!-- 右键菜单 -->
<ArtMenuRight
ref="contextMenuRef"
:menu-items="contextMenuItems"
:menu-width="120"
@select="handleContextMenuSelect"
/>
</ElCard>
</div>
@@ -220,6 +229,8 @@
import { useAuth } from '@/composables/useAuth'
import { formatDateTime } from '@/utils/business/format'
import ArtButtonTable from '@/components/core/forms/ArtButtonTable.vue'
import ArtMenuRight from '@/components/core/others/ArtMenuRight.vue'
import type { MenuItemType } from '@/components/core/others/ArtMenuRight.vue'
import { StorageService } from '@/api/modules/storage'
import type { IotCardImportTask, IotCardImportTaskStatus } from '@/types/api/card'
import type { Carrier } from '@/types/api'
@@ -237,6 +248,8 @@
const selectedCarrierId = ref<number>()
const carrierList = ref<Carrier[]>([])
const carrierLoading = ref(false)
const contextMenuRef = ref<InstanceType<typeof ArtMenuRight>>()
const currentRow = ref<IotCardImportTask | null>(null)
// 搜索表单初始值
const initialSearchState = {
@@ -324,8 +337,7 @@
{ label: '开始时间', prop: 'started_at' },
{ label: '完成时间', prop: 'completed_at' },
{ label: '错误信息', prop: 'error_message' },
{ label: '创建时间', prop: 'created_at' },
{ label: '操作', prop: 'operation' }
{ label: '创建时间', prop: 'created_at' }
]
const taskList = ref<IotCardImportTask[]>([])
@@ -445,36 +457,6 @@
label: '创建时间',
width: 180,
formatter: (row: IotCardImportTask) => formatDateTime(row.created_at)
},
{
prop: 'operation',
label: '操作',
width: 180,
fixed: 'right',
formatter: (row: IotCardImportTask) => {
const buttons = []
// 显示"查看详情"按钮
buttons.push(
h(ArtButtonTable, {
text: '详情',
onClick: () => viewDetail(row)
})
)
// 如果有失败数据,显示"失败数据"按钮
if (row.fail_count > 0) {
buttons.push(
h(ArtButtonTable, {
text: '失败数据',
type: 'danger',
onClick: () => downloadFailDataByRow(row)
})
)
}
return h('div', { style: 'display: flex; gap: 8px;' }, buttons)
}
}
])
@@ -827,6 +809,43 @@
uploading.value = false
}
}
// 右键菜单项配置
const contextMenuItems = computed((): MenuItemType[] => {
if (!currentRow.value) return []
const items: MenuItemType[] = []
items.push({ key: 'detail', label: '详情' })
if (currentRow.value.fail_count > 0) {
items.push({ key: 'failData', label: '失败数据' })
}
return items
})
// 处理表格行右键菜单
const handleRowContextMenu = (row: IotCardImportTask, column: any, event: MouseEvent) => {
event.preventDefault()
event.stopPropagation()
currentRow.value = row
contextMenuRef.value?.show(event)
}
// 处理右键菜单选择
const handleContextMenuSelect = (item: MenuItemType) => {
if (!currentRow.value) return
switch (item.key) {
case 'detail':
viewDetail(currentRow.value)
break
case 'failData':
downloadFailDataByRow(currentRow.value)
break
}
}
</script>
<style lang="scss" scoped>