<template>
|
<div class="task-page art-full-height">
|
<ArtSearchBar
|
v-model="searchForm"
|
:items="searchItems"
|
:showExpand="true"
|
@search="handleSearch"
|
@reset="handleReset"
|
/>
|
|
<ElCard class="art-table-card">
|
<ArtTableHeader v-model:columns="columnChecks" :loading="loading" @refresh="loadPageData">
|
<template #left>
|
<ElSpace wrap>
|
<ElButton
|
v-if="!autoRunEnabled"
|
type="primary"
|
plain
|
:loading="autoRunLoading"
|
@click="handleToggleAutoRun(true)"
|
>
|
{{ t('pages.task.buttons.autoRun') }}
|
</ElButton>
|
<ElButton
|
v-else
|
type="warning"
|
plain
|
:loading="autoRunLoading"
|
@click="handleToggleAutoRun(false)"
|
>
|
{{ t('pages.task.buttons.pauseAutoRun') }}
|
</ElButton>
|
</ElSpace>
|
</template>
|
</ArtTableHeader>
|
|
<ArtTable
|
:loading="loading"
|
:data="tableData"
|
:columns="columns"
|
:pagination="pagination"
|
@pagination:size-change="handleSizeChange"
|
@pagination:current-change="handleCurrentChange"
|
/>
|
</ElCard>
|
|
<TaskFlowStepDialog
|
v-model:visible="flowStepDialogVisible"
|
:task-row="activeTaskRow"
|
/>
|
|
<TaskDetailDrawer
|
v-model:visible="detailDrawerVisible"
|
:loading="detailLoading"
|
:detail="detailData"
|
:data="detailTableData"
|
:columns="detailColumns"
|
:pagination="detailPagination"
|
@refresh="loadDetailResources"
|
@size-change="handleDetailSizeChange"
|
@current-change="handleDetailCurrentChange"
|
@flow-step="handleOpenFlowStepFromDetail"
|
/>
|
</div>
|
</template>
|
|
<script setup>
|
import { ElMessage } from 'element-plus'
|
import { computed, h, onMounted, onUnmounted, reactive, ref } from 'vue'
|
import { useI18n } from 'vue-i18n'
|
import { useTableColumns } from '@/hooks/core/useTableColumns'
|
import { guardRequestWithMessage } from '@/utils/sys/requestGuard'
|
import {
|
fetchCheckTask,
|
fetchCompleteTask,
|
fetchPickTask,
|
fetchRemoveTask,
|
fetchTaskAutoRunFlag,
|
fetchTaskItemPage,
|
fetchTaskPage,
|
fetchTopTask,
|
fetchUpdateTaskAutoRunFlag
|
} from '@/api/task'
|
import TaskDetailDrawer from './modules/task-detail-drawer.vue'
|
import TaskExpandPanel from './modules/task-expand-panel.vue'
|
import TaskFlowStepDialog from './modules/task-flow-step-dialog.vue'
|
import { createTaskTableColumns } from './taskTable.columns'
|
import {
|
buildTaskPageQueryParams,
|
confirmTaskAction,
|
createTaskSearchState,
|
normalizeTaskItemRow,
|
normalizeTaskRow
|
} from './taskPage.helpers'
|
|
defineOptions({ name: 'Task' })
|
const { t } = useI18n()
|
|
const loading = ref(false)
|
const tableData = ref([])
|
const searchForm = ref(createTaskSearchState())
|
const detailDrawerVisible = ref(false)
|
const detailLoading = ref(false)
|
const detailData = ref({})
|
const detailTableData = ref([])
|
const activeTaskRow = ref(null)
|
const flowStepDialogVisible = ref(false)
|
const autoRunEnabled = ref(false)
|
const autoRunLoading = ref(false)
|
let refreshTimer = null
|
|
const pagination = reactive({
|
current: 1,
|
size: 20,
|
total: 0
|
})
|
|
const detailPagination = reactive({
|
current: 1,
|
size: 20,
|
total: 0
|
})
|
|
const searchItems = computed(() => [
|
{
|
label: t('pages.task.search.condition'),
|
key: 'condition',
|
type: 'input',
|
props: { clearable: true, placeholder: t('pages.task.placeholder.condition') }
|
},
|
{
|
label: t('pages.task.search.taskCode'),
|
key: 'taskCode',
|
type: 'input',
|
props: { clearable: true, placeholder: t('pages.task.placeholder.taskCode') }
|
},
|
{
|
label: t('pages.task.search.orgLoc'),
|
key: 'orgLoc',
|
type: 'input',
|
props: { clearable: true, placeholder: t('pages.task.placeholder.orgLoc') }
|
},
|
{
|
label: t('pages.task.search.targLoc'),
|
key: 'targLoc',
|
type: 'input',
|
props: { clearable: true, placeholder: t('pages.task.placeholder.targLoc') }
|
},
|
{
|
label: t('pages.task.search.barcode'),
|
key: 'barcode',
|
type: 'input',
|
props: { clearable: true, placeholder: t('pages.task.placeholder.barcode') }
|
}
|
])
|
|
const detailColumns = computed(() => [
|
{
|
type: 'globalIndex',
|
label: t('table.index'),
|
width: 72,
|
align: 'center'
|
},
|
{
|
prop: 'orderTypeLabel',
|
label: t('pages.orders.delivery.detail.type'),
|
minWidth: 120,
|
showOverflowTooltip: true
|
},
|
{
|
prop: 'wkTypeLabel',
|
label: t('pages.orders.delivery.detail.wkType'),
|
minWidth: 120,
|
showOverflowTooltip: true
|
},
|
{
|
prop: 'platWorkCode',
|
label: t('pages.orders.transfer.detail.relatedCode'),
|
minWidth: 150,
|
showOverflowTooltip: true
|
},
|
{
|
prop: 'platItemId',
|
label: t('pages.orders.delivery.table.platItemId'),
|
minWidth: 100,
|
showOverflowTooltip: true
|
},
|
{
|
prop: 'matnrCode',
|
label: t('pages.orders.delivery.table.matnrCode'),
|
minWidth: 150,
|
showOverflowTooltip: true
|
},
|
{
|
prop: 'maktx',
|
label: t('pages.orders.delivery.table.maktx'),
|
minWidth: 220,
|
showOverflowTooltip: true
|
},
|
{
|
prop: 'batch',
|
label: t('table.batch'),
|
minWidth: 140,
|
showOverflowTooltip: true
|
},
|
{
|
prop: 'unit',
|
label: t('table.unit'),
|
width: 100
|
},
|
{
|
prop: 'anfme',
|
label: t('pages.orders.delivery.table.anfme'),
|
width: 100,
|
align: 'right'
|
},
|
{
|
prop: 'updateByText',
|
label: t('pages.orders.delivery.detail.updateBy'),
|
minWidth: 120,
|
showOverflowTooltip: true
|
},
|
{
|
prop: 'updateTimeText',
|
label: t('pages.orders.delivery.detail.updateTime'),
|
minWidth: 180,
|
showOverflowTooltip: true
|
}
|
])
|
|
async function openDetailDrawer(row) {
|
activeTaskRow.value = row
|
detailData.value = normalizeTaskRow(row)
|
detailPagination.current = 1
|
detailDrawerVisible.value = true
|
await loadDetailResources()
|
}
|
|
function handleOpenFlowStepFromDetail() {
|
if (!activeTaskRow.value) {
|
return
|
}
|
flowStepDialogVisible.value = true
|
}
|
|
async function handleActionClick(action, row) {
|
try {
|
if (action.key === 'view') {
|
await openDetailDrawer(row)
|
return
|
}
|
|
if (action.key === 'flowStep') {
|
activeTaskRow.value = row
|
flowStepDialogVisible.value = true
|
return
|
}
|
|
if (action.key === 'complete') {
|
await confirmTaskAction(t('pages.task.messages.completeConfirm', { code: row.taskCode || '' }))
|
await fetchCompleteTask(row.id)
|
ElMessage.success(t('pages.task.messages.completeSuccess'))
|
} else if (action.key === 'remove') {
|
await confirmTaskAction(t('pages.task.messages.removeConfirm', { code: row.taskCode || '' }))
|
await fetchRemoveTask(row.id)
|
ElMessage.success(t('pages.task.messages.removeSuccess'))
|
} else if (action.key === 'check') {
|
await confirmTaskAction(t('pages.task.messages.checkConfirm', { code: row.taskCode || '' }))
|
await fetchCheckTask(row.id)
|
ElMessage.success(t('pages.task.messages.checkSuccess'))
|
} else if (action.key === 'pick') {
|
await confirmTaskAction(t('pages.task.messages.pickConfirm', { code: row.taskCode || '' }))
|
await fetchPickTask(row.id)
|
ElMessage.success(t('pages.task.messages.pickSuccess'))
|
} else if (action.key === 'top') {
|
await fetchTopTask(row.id)
|
ElMessage.success(t('pages.task.messages.topSuccess'))
|
}
|
|
await loadPageData()
|
if (detailDrawerVisible.value && activeTaskRow.value?.id === row.id) {
|
await loadDetailResources()
|
}
|
} catch (error) {
|
if (error === 'cancel') {
|
return
|
}
|
ElMessage.error(error?.message || t('pages.task.messages.actionFailed'))
|
}
|
}
|
|
const { columns, columnChecks } = useTableColumns(() =>
|
createTaskTableColumns({
|
handleActionClick,
|
createExpandContent: (row) => ({
|
name: 'TaskExpandPanelHost',
|
render() {
|
return h(TaskExpandPanel, { row })
|
}
|
})
|
})
|
)
|
|
function updatePaginationState(target, response, fallbackCurrent, fallbackSize) {
|
target.total = Number(response?.total || 0)
|
target.current = Number(response?.current || fallbackCurrent || 1)
|
target.size = Number(response?.size || fallbackSize || target.size || 20)
|
}
|
|
async function loadPageData() {
|
loading.value = true
|
try {
|
const response = await guardRequestWithMessage(
|
fetchTaskPage(
|
buildTaskPageQueryParams({
|
...searchForm.value,
|
current: pagination.current,
|
pageSize: pagination.size
|
})
|
),
|
{
|
records: [],
|
total: 0,
|
current: pagination.current,
|
size: pagination.size
|
},
|
{ timeoutMessage: t('pages.task.messages.listTimeout') }
|
)
|
tableData.value = Array.isArray(response?.records)
|
? response.records.map((record) => normalizeTaskRow(record))
|
: []
|
updatePaginationState(pagination, response, pagination.current, pagination.size)
|
} finally {
|
loading.value = false
|
}
|
}
|
|
async function loadAutoRunConfig() {
|
autoRunLoading.value = true
|
try {
|
const response = await guardRequestWithMessage(fetchTaskAutoRunFlag(), { val: false }, {
|
timeoutMessage: t('pages.task.messages.autoRunTimeout')
|
})
|
const rawValue = response?.val
|
autoRunEnabled.value =
|
rawValue === true || rawValue === 'true' || rawValue === 1 || rawValue === '1'
|
} finally {
|
autoRunLoading.value = false
|
}
|
}
|
|
async function handleToggleAutoRun(enabled) {
|
autoRunLoading.value = true
|
try {
|
await fetchUpdateTaskAutoRunFlag(enabled)
|
autoRunEnabled.value = enabled
|
ElMessage.success(enabled ? t('pages.task.messages.autoRunOnSuccess') : t('pages.task.messages.autoRunOffSuccess'))
|
} catch (error) {
|
ElMessage.error(error?.message || t('pages.task.messages.autoRunUpdateFailed'))
|
} finally {
|
autoRunLoading.value = false
|
}
|
}
|
|
async function loadDetailResources() {
|
if (!activeTaskRow.value?.id) {
|
return
|
}
|
|
detailLoading.value = true
|
try {
|
const taskItemResponse = await guardRequestWithMessage(
|
fetchTaskItemPage({
|
taskId: activeTaskRow.value.id,
|
current: detailPagination.current,
|
pageSize: detailPagination.size
|
}),
|
{
|
records: [],
|
total: 0,
|
current: detailPagination.current,
|
size: detailPagination.size
|
},
|
{ timeoutMessage: t('pages.task.messages.itemsTimeout') }
|
)
|
|
detailData.value = normalizeTaskRow(activeTaskRow.value)
|
detailTableData.value = Array.isArray(taskItemResponse?.records)
|
? taskItemResponse.records.map((record) => normalizeTaskItemRow(record))
|
: []
|
updatePaginationState(detailPagination, taskItemResponse, detailPagination.current, detailPagination.size)
|
} catch (error) {
|
detailTableData.value = []
|
ElMessage.error(error?.message || t('pages.task.messages.detailLoadFailed'))
|
} finally {
|
detailLoading.value = false
|
}
|
}
|
|
function handleSearch(params) {
|
searchForm.value = {
|
...searchForm.value,
|
...params
|
}
|
pagination.current = 1
|
loadPageData()
|
}
|
|
function handleReset() {
|
searchForm.value = createTaskSearchState()
|
pagination.current = 1
|
pagination.size = 20
|
loadPageData()
|
}
|
|
function handleSizeChange(size) {
|
pagination.size = size
|
pagination.current = 1
|
loadPageData()
|
}
|
|
function handleCurrentChange(current) {
|
pagination.current = current
|
loadPageData()
|
}
|
|
function handleDetailSizeChange(size) {
|
detailPagination.size = size
|
detailPagination.current = 1
|
loadDetailResources()
|
}
|
|
function handleDetailCurrentChange(current) {
|
detailPagination.current = current
|
loadDetailResources()
|
}
|
|
function startAutoRefresh() {
|
clearAutoRefresh()
|
refreshTimer = window.setInterval(() => {
|
void loadPageData()
|
}, 5000)
|
}
|
|
function clearAutoRefresh() {
|
if (refreshTimer) {
|
window.clearInterval(refreshTimer)
|
refreshTimer = null
|
}
|
}
|
|
onMounted(async () => {
|
await Promise.all([loadPageData(), loadAutoRunConfig()])
|
startAutoRefresh()
|
})
|
|
onUnmounted(() => {
|
clearAutoRefresh()
|
})
|
</script>
|