fix: 将导出列表分成三个模块
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m40s
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m40s
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<ExportTaskList />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ExportTaskList from '../export-task-list/index.vue'
|
||||
|
||||
defineOptions({ name: 'ExportDeviceTaskList' })
|
||||
</script>
|
||||
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<ExportTaskList />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ExportTaskList from '../export-task-list/index.vue'
|
||||
|
||||
defineOptions({ name: 'ExportIotCardTaskList' })
|
||||
</script>
|
||||
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
<ExportTaskList />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ExportTaskList from '../export-task-list/index.vue'
|
||||
|
||||
defineOptions({ name: 'ExportOrderTaskList' })
|
||||
</script>
|
||||
@@ -10,23 +10,11 @@
|
||||
返回
|
||||
</ElButton>
|
||||
<h2 class="detail-title">导出任务详情</h2>
|
||||
<div class="detail-actions" v-if="taskDetail">
|
||||
<ElButton
|
||||
v-if="
|
||||
taskDetail.status === ExportTaskStatus.COMPLETED && hasAuth('export_task:download')
|
||||
"
|
||||
type="primary"
|
||||
@click="downloadTask"
|
||||
>
|
||||
<div class="detail-actions" v-if="taskDetail && canViewDetail">
|
||||
<ElButton v-if="canDownloadTask" type="primary" @click="downloadTask">
|
||||
下载文件
|
||||
</ElButton>
|
||||
<ElButton
|
||||
v-if="canCancelTask && hasAuth('export_task:cancel')"
|
||||
type="danger"
|
||||
@click="cancelTask"
|
||||
>
|
||||
取消任务
|
||||
</ElButton>
|
||||
<ElButton v-if="canCancelTask" type="danger" @click="cancelTask"> 取消任务 </ElButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -36,8 +24,12 @@
|
||||
</ElIcon>
|
||||
<div>加载中...</div>
|
||||
</div>
|
||||
<DetailPage v-else-if="taskDetail" :sections="detailSections" :data="taskDetail" />
|
||||
<ElEmpty v-else description="暂无详情" />
|
||||
<DetailPage
|
||||
v-else-if="taskDetail && canViewDetail"
|
||||
:sections="detailSections"
|
||||
:data="taskDetail"
|
||||
/>
|
||||
<ElEmpty v-else :description="forbidden ? '暂无权限查看该导出任务详情' : '暂无详情'" />
|
||||
</ElCard>
|
||||
</div>
|
||||
</ArtTableFullScreen>
|
||||
@@ -52,8 +44,9 @@
|
||||
import type { DetailSection } from '@/components/common/DetailPage.vue'
|
||||
import { ExportTaskService } from '@/api/modules'
|
||||
import { useAuth } from '@/composables/useAuth'
|
||||
import { getExportTaskSceneConfig, getExportTaskSceneName } from '@/config/constants'
|
||||
import { formatDateTime } from '@/utils/business/format'
|
||||
import type { ExportTaskDetail, ExportTaskScene } from '@/types/api'
|
||||
import type { ExportTaskDetail } from '@/types/api'
|
||||
import { ExportTaskStatus } from '@/types/api'
|
||||
|
||||
defineOptions({ name: 'ExportTaskDetail' })
|
||||
@@ -62,17 +55,22 @@
|
||||
const router = useRouter()
|
||||
const { hasAuth } = useAuth()
|
||||
const loading = ref(false)
|
||||
const forbidden = ref(false)
|
||||
const taskDetail = ref<ExportTaskDetail | null>(null)
|
||||
|
||||
const getSceneName = (scene?: ExportTaskScene) => {
|
||||
const sceneMap: Record<ExportTaskScene, string> = {
|
||||
device: '设备管理',
|
||||
iot_card: 'IoT卡管理',
|
||||
order: '订单管理'
|
||||
}
|
||||
|
||||
return scene ? sceneMap[scene] : '-'
|
||||
}
|
||||
const taskPermissions = computed(
|
||||
() => getExportTaskSceneConfig(taskDetail.value?.scene)?.permissions
|
||||
)
|
||||
const canViewDetail = computed(
|
||||
() => !!taskPermissions.value && hasAuth(taskPermissions.value.detail)
|
||||
)
|
||||
const canDownloadTask = computed(
|
||||
() =>
|
||||
canViewDetail.value &&
|
||||
taskDetail.value?.status === ExportTaskStatus.COMPLETED &&
|
||||
!!taskPermissions.value &&
|
||||
hasAuth(taskPermissions.value.download)
|
||||
)
|
||||
|
||||
const getStatusTagType = (status?: ExportTaskStatus) => {
|
||||
const statusTypeMap: Record<
|
||||
@@ -89,10 +87,14 @@
|
||||
return status ? statusTypeMap[status] : 'info'
|
||||
}
|
||||
|
||||
const canCancelTask = computed(() =>
|
||||
[ExportTaskStatus.PENDING, ExportTaskStatus.PROCESSING].includes(
|
||||
taskDetail.value?.status as ExportTaskStatus
|
||||
)
|
||||
const canCancelTask = computed(
|
||||
() =>
|
||||
canViewDetail.value &&
|
||||
[ExportTaskStatus.PENDING, ExportTaskStatus.PROCESSING].includes(
|
||||
taskDetail.value?.status as ExportTaskStatus
|
||||
) &&
|
||||
!!taskPermissions.value &&
|
||||
hasAuth(taskPermissions.value.cancel)
|
||||
)
|
||||
|
||||
const detailSections = computed((): DetailSection[] => [
|
||||
@@ -102,7 +104,7 @@
|
||||
{ label: '任务编号', prop: 'task_no', formatter: (value: string) => value || '-' },
|
||||
{
|
||||
label: '导出场景',
|
||||
render: (data: ExportTaskDetail) => h(ElTag, {}, () => getSceneName(data.scene))
|
||||
render: (data: ExportTaskDetail) => h(ElTag, {}, () => getExportTaskSceneName(data.scene))
|
||||
},
|
||||
{
|
||||
label: '任务状态',
|
||||
@@ -174,12 +176,13 @@
|
||||
fullWidth: true,
|
||||
render: (data: ExportTaskDetail) => {
|
||||
if (!data.download_url) return h('span', '-')
|
||||
if (!canDownloadTask.value) return h('span', '-')
|
||||
return h(
|
||||
ElButton,
|
||||
{
|
||||
type: 'primary',
|
||||
link: true,
|
||||
onClick: () => window.open(data.download_url, '_blank')
|
||||
onClick: () => downloadTask()
|
||||
},
|
||||
() => '打开下载地址'
|
||||
)
|
||||
@@ -209,10 +212,15 @@
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
forbidden.value = false
|
||||
try {
|
||||
const res = await ExportTaskService.getExportTaskDetail(taskId)
|
||||
if (res.code === 0) {
|
||||
taskDetail.value = res.data
|
||||
if (!canViewDetail.value) {
|
||||
forbidden.value = true
|
||||
ElMessage.warning('您没有查看该导出任务详情的权限')
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(res.msg || '获取导出任务详情失败')
|
||||
}
|
||||
@@ -225,6 +233,11 @@
|
||||
}
|
||||
|
||||
const downloadTask = () => {
|
||||
if (!canDownloadTask.value) {
|
||||
ElMessage.warning('您没有下载该导出任务的权限')
|
||||
return
|
||||
}
|
||||
|
||||
if (!taskDetail.value?.download_url) {
|
||||
ElMessage.warning('当前任务暂无可用下载地址')
|
||||
return
|
||||
@@ -235,6 +248,10 @@
|
||||
|
||||
const cancelTask = () => {
|
||||
if (!taskDetail.value) return
|
||||
if (!canCancelTask.value) {
|
||||
ElMessage.warning('您没有取消该导出任务的权限')
|
||||
return
|
||||
}
|
||||
|
||||
ElMessageBox.confirm(`确定取消导出任务 ${taskDetail.value.task_no} 吗?`, '取消确认', {
|
||||
confirmButtonText: '确定',
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
v-model:filter="searchForm"
|
||||
:items="searchFormItems"
|
||||
label-width="110"
|
||||
:show-expand="false"
|
||||
@reset="handleReset"
|
||||
@search="handleSearch"
|
||||
/>
|
||||
@@ -38,27 +39,36 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h, onMounted, reactive, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { computed, h, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox, ElProgress, ElTag } from 'element-plus'
|
||||
import { ExportTaskService } from '@/api/modules'
|
||||
import { useAuth } from '@/composables/useAuth'
|
||||
import { useCheckedColumns } from '@/composables/useCheckedColumns'
|
||||
import { formatDateTime } from '@/utils/business/format'
|
||||
import { RoutesAlias } from '@/router/routesAlias'
|
||||
import { getExportTaskSceneConfig } from '@/config/constants'
|
||||
import type { SearchFormItem } from '@/types'
|
||||
import type { ExportTaskItem, ExportTaskScene } from '@/types/api'
|
||||
import { ExportTaskStatus } from '@/types/api'
|
||||
|
||||
defineOptions({ name: 'ExportTaskList' })
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { hasAuth } = useAuth()
|
||||
const loading = ref(false)
|
||||
const taskList = ref<ExportTaskItem[]>([])
|
||||
const defaultSceneConfig = getExportTaskSceneConfig('device')!
|
||||
|
||||
const routeScene = computed(() => route.meta.exportTaskScene as ExportTaskScene | undefined)
|
||||
const sceneConfig = computed(
|
||||
() => getExportTaskSceneConfig(routeScene.value) || defaultSceneConfig
|
||||
)
|
||||
const currentScene = computed(() => sceneConfig.value.scene)
|
||||
const currentPermissions = computed(() => sceneConfig.value.permissions)
|
||||
|
||||
const initialSearchState = {
|
||||
scene: undefined as ExportTaskScene | undefined,
|
||||
status: undefined as ExportTaskStatus | undefined,
|
||||
dateRange: [] as string[],
|
||||
start_time: '',
|
||||
@@ -72,12 +82,6 @@
|
||||
total: 0
|
||||
})
|
||||
|
||||
const sceneOptions = [
|
||||
{ label: '设备管理', value: 'device' },
|
||||
{ label: 'IoT卡管理', value: 'iot_card' },
|
||||
{ label: '订单管理', value: 'order' }
|
||||
]
|
||||
|
||||
const statusOptions = [
|
||||
{ label: '待处理', value: ExportTaskStatus.PENDING },
|
||||
{ label: '处理中', value: ExportTaskStatus.PROCESSING },
|
||||
@@ -87,13 +91,6 @@
|
||||
]
|
||||
|
||||
const searchFormItems: SearchFormItem[] = [
|
||||
{
|
||||
label: '导出场景',
|
||||
prop: 'scene',
|
||||
type: 'select',
|
||||
config: { clearable: true, placeholder: '请选择导出场景' },
|
||||
options: () => sceneOptions
|
||||
},
|
||||
{
|
||||
label: '任务状态',
|
||||
prop: 'status',
|
||||
@@ -117,7 +114,6 @@
|
||||
|
||||
const columnOptions = [
|
||||
{ label: '任务编号', prop: 'task_no' },
|
||||
{ label: '场景', prop: 'scene' },
|
||||
{ label: '状态', prop: 'status_name' },
|
||||
{ label: '进度', prop: 'progress' },
|
||||
{ label: '格式', prop: 'format' },
|
||||
@@ -144,12 +140,6 @@
|
||||
row.task_no || '-'
|
||||
)
|
||||
},
|
||||
{
|
||||
prop: 'scene',
|
||||
label: '场景',
|
||||
width: 120,
|
||||
formatter: (row: ExportTaskItem) => getSceneName(row.scene)
|
||||
},
|
||||
{
|
||||
prop: 'status_name',
|
||||
label: '状态',
|
||||
@@ -181,11 +171,6 @@
|
||||
}
|
||||
])
|
||||
|
||||
const getSceneName = (scene?: ExportTaskScene) => {
|
||||
const option = sceneOptions.find((item) => item.value === scene)
|
||||
return option?.label || '-'
|
||||
}
|
||||
|
||||
const getStatusTagType = (status: ExportTaskStatus) => {
|
||||
const statusTypeMap: Record<
|
||||
ExportTaskStatus,
|
||||
@@ -218,7 +203,7 @@
|
||||
const res = await ExportTaskService.getExportTasks({
|
||||
page: pagination.page,
|
||||
page_size: pagination.pageSize,
|
||||
scene: searchForm.scene,
|
||||
scene: currentScene.value,
|
||||
status: searchForm.status,
|
||||
start_time: searchForm.start_time || undefined,
|
||||
end_time: searchForm.end_time || undefined
|
||||
@@ -272,8 +257,12 @@
|
||||
return res.data
|
||||
}
|
||||
|
||||
const getRowPermissions = (row: ExportTaskItem) => {
|
||||
return getExportTaskSceneConfig(row.scene)?.permissions || currentPermissions.value
|
||||
}
|
||||
|
||||
const goDetail = (row: ExportTaskItem) => {
|
||||
if (!hasAuth('export_task:detail')) {
|
||||
if (!hasAuth(getRowPermissions(row).detail)) {
|
||||
ElMessage.warning('您没有查看导出任务详情的权限')
|
||||
return
|
||||
}
|
||||
@@ -285,6 +274,11 @@
|
||||
}
|
||||
|
||||
const downloadTask = async (row: ExportTaskItem) => {
|
||||
if (!hasAuth(getRowPermissions(row).download)) {
|
||||
ElMessage.warning('您没有下载导出任务的权限')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const detail = await getTaskDetail(row.id)
|
||||
if (!detail.download_url) {
|
||||
@@ -300,6 +294,11 @@
|
||||
}
|
||||
|
||||
const cancelTask = (row: ExportTaskItem) => {
|
||||
if (!hasAuth(getRowPermissions(row).cancel)) {
|
||||
ElMessage.warning('您没有取消导出任务的权限')
|
||||
return
|
||||
}
|
||||
|
||||
ElMessageBox.confirm(`确定取消导出任务 ${row.task_no} 吗?`, '取消确认', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
@@ -322,14 +321,15 @@
|
||||
|
||||
const getActions = (row: ExportTaskItem) => {
|
||||
const actions: any[] = []
|
||||
const permissions = getRowPermissions(row)
|
||||
|
||||
if (row.status === ExportTaskStatus.COMPLETED && hasAuth('export_task:download')) {
|
||||
if (row.status === ExportTaskStatus.COMPLETED && hasAuth(permissions.download)) {
|
||||
actions.push({ label: '下载', handler: () => downloadTask(row), type: 'primary' })
|
||||
}
|
||||
|
||||
if (
|
||||
[ExportTaskStatus.PENDING, ExportTaskStatus.PROCESSING].includes(row.status) &&
|
||||
hasAuth('export_task:cancel')
|
||||
hasAuth(permissions.cancel)
|
||||
) {
|
||||
actions.push({ label: '取消', handler: () => cancelTask(row), type: 'danger' })
|
||||
}
|
||||
@@ -340,6 +340,12 @@
|
||||
onMounted(() => {
|
||||
getTableData()
|
||||
})
|
||||
|
||||
watch(currentScene, () => {
|
||||
Object.assign(searchForm, { ...initialSearchState })
|
||||
pagination.page = 1
|
||||
getTableData()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -997,7 +997,7 @@
|
||||
scene="iot_card"
|
||||
:query="exportQuery"
|
||||
confirm-permission="iot_card:export"
|
||||
title="导出IoT卡"
|
||||
title="导出IOT卡"
|
||||
/>
|
||||
</ElCard>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user