350 lines
11 KiB
Vue
350 lines
11 KiB
Vue
<script setup lang="ts">
|
|
import { markRaw, onMounted, ref } from 'vue';
|
|
import { useRoute } from 'vue-router';
|
|
|
|
import {
|
|
CaretRight,
|
|
CircleCloseFilled,
|
|
Delete,
|
|
MoreFilled,
|
|
Plus,
|
|
Tickets,
|
|
} from '@element-plus/icons-vue';
|
|
import {
|
|
ElButton,
|
|
ElDropdown,
|
|
ElDropdownItem,
|
|
ElDropdownMenu,
|
|
ElMessage,
|
|
ElMessageBox,
|
|
ElTable,
|
|
ElTableColumn,
|
|
} from 'element-plus';
|
|
|
|
import { api } from '#/api/request';
|
|
import HeaderSearch from '#/components/headerSearch/HeaderSearch.vue';
|
|
import ListPageShell from '#/components/page/ListPageShell.vue';
|
|
import PageData from '#/components/page/PageData.vue';
|
|
import {
|
|
buildListRouteFullPath,
|
|
mergeListRouteStateQuery,
|
|
parseListRouteState,
|
|
watchListRouteState,
|
|
} from '#/composables/useListRouteState';
|
|
import { $t } from '#/locales';
|
|
import { router } from '#/router';
|
|
import { withListReturnTo } from '#/router/list-return-context';
|
|
import { useDictStore } from '#/store';
|
|
|
|
import { sysJobListRouteSchema } from './sys-job-list-route-state';
|
|
import SysJobModal from './SysJobModal.vue';
|
|
|
|
const route = useRoute();
|
|
const initialListState = parseListRouteState(
|
|
route.query,
|
|
sysJobListRouteSchema,
|
|
);
|
|
|
|
onMounted(() => {
|
|
initDict();
|
|
});
|
|
|
|
const pageDataRef = ref();
|
|
const searchKeyword = ref(initialListState.keyword);
|
|
const currentPageNumber = ref(initialListState.pageNumber);
|
|
const currentPageSize = ref(initialListState.pageSize);
|
|
watchListRouteState(route, sysJobListRouteSchema, (state) => {
|
|
searchKeyword.value = state.keyword;
|
|
currentPageNumber.value = state.pageNumber;
|
|
currentPageSize.value = state.pageSize;
|
|
pageDataRef.value?.restoreState?.({
|
|
pageNumber: state.pageNumber,
|
|
pageSize: state.pageSize,
|
|
queryParams: {
|
|
keyword: state.keyword || undefined,
|
|
},
|
|
});
|
|
});
|
|
const saveDialog = ref();
|
|
const dictStore = useDictStore();
|
|
const headerButtons = [
|
|
{
|
|
key: 'create',
|
|
text: $t('button.add'),
|
|
icon: markRaw(Plus),
|
|
type: 'primary',
|
|
data: { action: 'create' },
|
|
permission: '/api/v1/sysJob/save',
|
|
},
|
|
];
|
|
|
|
function initDict() {
|
|
dictStore.fetchDictionary('jobType');
|
|
dictStore.fetchDictionary('jobStatus');
|
|
dictStore.fetchDictionary('yesOrNo');
|
|
dictStore.fetchDictionary('misfirePolicy');
|
|
}
|
|
const handleSearch = (params: string) => {
|
|
searchKeyword.value = params;
|
|
pageDataRef.value.setQuery({
|
|
keyword: params || undefined,
|
|
});
|
|
};
|
|
function reloadCurrentList() {
|
|
pageDataRef.value?.reload?.();
|
|
}
|
|
function showDialog(row: any) {
|
|
saveDialog.value.openDialog({ ...row });
|
|
}
|
|
function remove(row: any) {
|
|
ElMessageBox.confirm($t('message.deleteAlert'), $t('message.noticeTitle'), {
|
|
confirmButtonText: $t('message.ok'),
|
|
cancelButtonText: $t('message.cancel'),
|
|
type: 'warning',
|
|
beforeClose: (action, instance, done) => {
|
|
if (action === 'confirm') {
|
|
instance.confirmButtonLoading = true;
|
|
api
|
|
.post('/api/v1/sysJob/remove', { id: row.id })
|
|
.then((res) => {
|
|
instance.confirmButtonLoading = false;
|
|
if (res.errorCode === 0) {
|
|
ElMessage.success(res.message);
|
|
reloadCurrentList();
|
|
done();
|
|
}
|
|
})
|
|
.catch(() => {
|
|
instance.confirmButtonLoading = false;
|
|
});
|
|
} else {
|
|
done();
|
|
}
|
|
},
|
|
}).catch(() => {});
|
|
}
|
|
function start(row: any) {
|
|
ElMessageBox.confirm($t('message.startAlert'), $t('message.noticeTitle'), {
|
|
confirmButtonText: $t('message.ok'),
|
|
cancelButtonText: $t('message.cancel'),
|
|
type: 'warning',
|
|
beforeClose: (action, instance, done) => {
|
|
if (action === 'confirm') {
|
|
instance.confirmButtonLoading = true;
|
|
api.get(`/api/v1/sysJob/start?id=${row.id}`).then((res) => {
|
|
instance.confirmButtonLoading = false;
|
|
if (res.errorCode === 0) {
|
|
ElMessage.success(res.message);
|
|
reloadCurrentList();
|
|
done();
|
|
}
|
|
});
|
|
} else {
|
|
done();
|
|
}
|
|
},
|
|
});
|
|
}
|
|
function stop(row: any) {
|
|
ElMessageBox.confirm($t('message.stopAlert'), $t('message.noticeTitle'), {
|
|
confirmButtonText: $t('message.ok'),
|
|
cancelButtonText: $t('message.cancel'),
|
|
type: 'warning',
|
|
beforeClose: (action, instance, done) => {
|
|
if (action === 'confirm') {
|
|
instance.confirmButtonLoading = true;
|
|
api.get(`/api/v1/sysJob/stop?id=${row.id}`).then((res) => {
|
|
instance.confirmButtonLoading = false;
|
|
if (res.errorCode === 0) {
|
|
ElMessage.success(res.message);
|
|
reloadCurrentList();
|
|
done();
|
|
}
|
|
});
|
|
} else {
|
|
done();
|
|
}
|
|
},
|
|
});
|
|
}
|
|
function toLogPage(row: any) {
|
|
router.push({
|
|
name: 'SysJobLog',
|
|
query: {
|
|
jobId: row.id,
|
|
...withListReturnTo(currentListFullPath()),
|
|
},
|
|
});
|
|
}
|
|
|
|
function currentListFullPath() {
|
|
return buildListRouteFullPath(
|
|
router,
|
|
route.query,
|
|
{
|
|
keyword: searchKeyword.value,
|
|
pageNumber: currentPageNumber.value,
|
|
pageSize: currentPageSize.value,
|
|
},
|
|
sysJobListRouteSchema,
|
|
);
|
|
}
|
|
|
|
function handlePageStateChange(state: {
|
|
pageNumber: number;
|
|
pageSize: number;
|
|
}) {
|
|
currentPageNumber.value = state.pageNumber;
|
|
currentPageSize.value = state.pageSize;
|
|
const query = mergeListRouteStateQuery(
|
|
route.query,
|
|
{
|
|
keyword: searchKeyword.value,
|
|
pageNumber: state.pageNumber,
|
|
pageSize: state.pageSize,
|
|
},
|
|
sysJobListRouteSchema,
|
|
);
|
|
const target = router.resolve({ path: sysJobListRouteSchema.path, query });
|
|
if (target.fullPath !== route.fullPath) void router.replace(target);
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex h-full flex-col gap-6 p-6">
|
|
<SysJobModal ref="saveDialog" @reload="reloadCurrentList" />
|
|
<ListPageShell>
|
|
<template #filters>
|
|
<HeaderSearch
|
|
:buttons="headerButtons"
|
|
:initial-value="searchKeyword"
|
|
@search="handleSearch"
|
|
@button-click="showDialog({})"
|
|
/>
|
|
</template>
|
|
<PageData
|
|
ref="pageDataRef"
|
|
page-url="/api/v1/sysJob/page"
|
|
:page-size="initialListState.pageSize"
|
|
:initial-page-number="initialListState.pageNumber"
|
|
:initial-query-params="{
|
|
keyword: initialListState.keyword || undefined,
|
|
}"
|
|
@state-change="handlePageStateChange"
|
|
>
|
|
<template #default="{ pageList }">
|
|
<ElTable :data="pageList" border>
|
|
<ElTableColumn prop="jobName" :label="$t('sysJob.jobName')">
|
|
<template #default="{ row }">
|
|
{{ row.jobName }}
|
|
</template>
|
|
</ElTableColumn>
|
|
<ElTableColumn prop="jobType" :label="$t('sysJob.jobType')">
|
|
<template #default="{ row }">
|
|
{{ dictStore.getDictLabel('jobType', row.jobType) }}
|
|
</template>
|
|
</ElTableColumn>
|
|
<ElTableColumn
|
|
prop="cronExpression"
|
|
:label="$t('sysJob.cronExpression')"
|
|
>
|
|
<template #default="{ row }">
|
|
{{ row.cronExpression }}
|
|
</template>
|
|
</ElTableColumn>
|
|
<ElTableColumn
|
|
prop="allowConcurrent"
|
|
:label="$t('sysJob.allowConcurrent')"
|
|
>
|
|
<template #default="{ row }">
|
|
{{ dictStore.getDictLabel('yesOrNo', row.allowConcurrent) }}
|
|
</template>
|
|
</ElTableColumn>
|
|
<ElTableColumn
|
|
prop="misfirePolicy"
|
|
:label="$t('sysJob.misfirePolicy')"
|
|
>
|
|
<template #default="{ row }">
|
|
{{ dictStore.getDictLabel('misfirePolicy', row.misfirePolicy) }}
|
|
</template>
|
|
</ElTableColumn>
|
|
<ElTableColumn prop="status" :label="$t('sysJob.status')">
|
|
<template #default="{ row }">
|
|
{{ dictStore.getDictLabel('jobStatus', row.status) }}
|
|
</template>
|
|
</ElTableColumn>
|
|
<ElTableColumn prop="created" :label="$t('sysJob.created')">
|
|
<template #default="{ row }">
|
|
{{ row.created }}
|
|
</template>
|
|
</ElTableColumn>
|
|
<ElTableColumn prop="remark" :label="$t('sysJob.remark')">
|
|
<template #default="{ row }">
|
|
{{ row.remark }}
|
|
</template>
|
|
</ElTableColumn>
|
|
<ElTableColumn
|
|
:label="$t('common.handle')"
|
|
width="90"
|
|
align="right"
|
|
>
|
|
<template #default="{ row }">
|
|
<div class="flex items-center gap-3">
|
|
<ElButton link type="primary" @click="showDialog(row)">
|
|
{{ $t('button.edit') }}
|
|
</ElButton>
|
|
|
|
<ElDropdown>
|
|
<ElButton link :icon="MoreFilled" />
|
|
|
|
<template #dropdown>
|
|
<ElDropdownMenu>
|
|
<div
|
|
v-if="row.status === 0"
|
|
v-access:code="'/api/v1/sysJob/save'"
|
|
>
|
|
<ElDropdownItem @click="start(row)">
|
|
<ElButton :icon="CaretRight" link>
|
|
{{ $t('button.start') }}
|
|
</ElButton>
|
|
</ElDropdownItem>
|
|
</div>
|
|
<div
|
|
v-if="row.status === 1"
|
|
v-access:code="'/api/v1/sysJob/save'"
|
|
>
|
|
<ElDropdownItem @click="stop(row)">
|
|
<ElButton :icon="CircleCloseFilled" link>
|
|
{{ $t('button.stop') }}
|
|
</ElButton>
|
|
</ElDropdownItem>
|
|
</div>
|
|
<div v-access:code="'/api/v1/sysJob/query'">
|
|
<ElDropdownItem @click="toLogPage(row)">
|
|
<ElButton :icon="Tickets" link>
|
|
{{ $t('button.log') }}
|
|
</ElButton>
|
|
</ElDropdownItem>
|
|
</div>
|
|
<div v-access:code="'/api/v1/sysJob/remove'">
|
|
<ElDropdownItem @click="remove(row)">
|
|
<ElButton type="danger" :icon="Delete" link>
|
|
{{ $t('button.delete') }}
|
|
</ElButton>
|
|
</ElDropdownItem>
|
|
</div>
|
|
</ElDropdownMenu>
|
|
</template>
|
|
</ElDropdown>
|
|
</div>
|
|
</template>
|
|
</ElTableColumn>
|
|
</ElTable>
|
|
</template>
|
|
</PageData>
|
|
</ListPageShell>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped></style>
|