vue-pro/yudao-ui-admin-vue3/src/views/infra/job/index.vue

325 lines
9.7 KiB
Vue
Raw Normal View History

2022-11-22 17:07:30 +08:00
<template>
<ContentWrap>
<!-- 列表 -->
<vxe-grid ref="xGrid" v-bind="gridOptions" class="xtable-scrollbar">
<template #toolbar_buttons>
<!-- 操作新增 -->
<XButton
type="primary"
preIcon="ep:zoom-in"
:title="t('action.add')"
v-hasPermi="['infra:job:create']"
@click="handleCreate()"
/>
<!-- 操作导出 -->
<XButton
type="warning"
preIcon="ep:download"
:title="t('action.export')"
v-hasPermi="['infra:job:export']"
@click="handleExport()"
/>
<XButton
type="info"
preIcon="ep:zoom-in"
title="执行日志"
v-hasPermi="['infra:job:query']"
@click="handleJobLog"
/>
</template>
<template #actionbtns_default="{ row }">
<!-- 操作修改 -->
<XTextButton
preIcon="ep:edit"
:title="t('action.edit')"
v-hasPermi="['infra:job:update']"
@click="handleUpdate(row.id)"
/>
2022-11-29 14:47:15 +08:00
<XTextButton
preIcon="ep:edit"
:title="row.status === InfraJobStatusEnum.STOP ? '开启' : '暂停'"
2022-11-22 17:07:30 +08:00
v-hasPermi="['infra:job:update']"
@click="handleChangeStatus(row)"
/>
<!-- 操作删除 -->
<XTextButton
preIcon="ep:delete"
:title="t('action.del')"
v-hasPermi="['infra:job:delete']"
@click="handleDelete(row.id)"
/>
2022-11-29 14:47:15 +08:00
<el-dropdown class="p-0.5" v-hasPermi="['infra:job:trigger', 'infra:job:query']">
<XTextButton title="更多" postIcon="ep:arrow-down" />
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>
<!-- 操作执行 -->
<XTextButton
preIcon="ep:view"
title="执行一次"
v-hasPermi="['infra:job:trigger']"
@click="handleRun(row)"
/>
</el-dropdown-item>
<el-dropdown-item>
<!-- 操作详情 -->
<XTextButton
preIcon="ep:view"
:title="t('action.detail')"
v-hasPermi="['infra:job:query']"
@click="handleDetail(row.id)"
/>
</el-dropdown-item>
<el-dropdown-item>
<!-- 操作日志 -->
<XTextButton
preIcon="ep:view"
title="调度日志"
v-hasPermi="['infra:job:query']"
@click="handleJobLog(row.id)"
/>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
2022-11-22 17:07:30 +08:00
</template>
</vxe-grid>
</ContentWrap>
<XModal v-model="dialogVisible" :title="dialogTitle">
<!-- 对话框(添加 / 修改) -->
<Form
v-if="['create', 'update'].includes(actionType)"
:schema="allSchemas.formSchema"
:rules="rules"
ref="formRef"
>
<template #cronExpression>
<Crontab v-model="cronExpression" :shortcuts="shortcuts" />
</template>
</Form>
<!-- 对话框(详情) -->
<Descriptions
v-if="actionType === 'detail'"
:schema="allSchemas.detailSchema"
:data="detailRef"
>
<template #retryInterval="{ row }">
<span>{{ row.retryInterval + '毫秒' }} </span>
</template>
<template #monitorTimeout="{ row }">
<span>{{ row.monitorTimeout > 0 ? row.monitorTimeout + ' 毫秒' : '未开启' }}</span>
</template>
2022-11-28 23:13:20 +08:00
<template #nextTimes>
<span>{{ Array.from(nextTimes, (x) => parseTime(x)).join('; ') }}</span>
</template>
2022-11-22 17:07:30 +08:00
</Descriptions>
<!-- 操作按钮 -->
<template #footer>
<!-- 按钮保存 -->
<XButton
v-if="['create', 'update'].includes(actionType)"
type="primary"
:title="t('action.save')"
:loading="actionLoading"
@click="submitForm()"
/>
<!-- 按钮关闭 -->
<XButton :loading="actionLoading" :title="t('dialog.close')" @click="dialogVisible = false" />
</template>
</XModal>
</template>
2022-11-23 22:26:25 +08:00
<script setup lang="ts" name="Job">
2022-07-18 19:06:37 +08:00
import { ref, unref } from 'vue'
2022-11-22 17:07:30 +08:00
import { useRouter } from 'vue-router'
2022-11-29 14:47:15 +08:00
import { ElDropdown, ElDropdownMenu, ElDropdownItem } from 'element-plus'
2022-07-18 19:06:37 +08:00
import { useI18n } from '@/hooks/web/useI18n'
2022-11-22 17:07:30 +08:00
import { useMessage } from '@/hooks/web/useMessage'
import { useVxeGrid } from '@/hooks/web/useVxeGrid'
import { VxeGridInstance } from 'vxe-table'
2022-07-18 19:06:37 +08:00
import { FormExpose } from '@/components/Form'
2022-11-22 17:07:30 +08:00
import { Crontab } from '@/components/Crontab'
import * as JobApi from '@/api/infra/job'
2022-07-18 19:06:37 +08:00
import { rules, allSchemas } from './job.data'
2022-07-29 01:25:44 +08:00
import { InfraJobStatusEnum } from '@/utils/constants'
2022-11-22 17:07:30 +08:00
2022-07-18 19:06:37 +08:00
const { t } = useI18n() // 国际化
2022-11-22 17:07:30 +08:00
const message = useMessage() // 消息弹窗
2022-07-18 19:06:37 +08:00
const { push } = useRouter()
2022-11-22 17:07:30 +08:00
// 列表相关的变量
const xGrid = ref<VxeGridInstance>() // 列表 Grid Ref
const { gridOptions, getList, deleteData, exportList } = useVxeGrid<JobApi.JobVO>({
allSchemas: allSchemas,
2022-07-18 19:06:37 +08:00
getListApi: JobApi.getJobPageApi,
2022-11-22 17:07:30 +08:00
deleteApi: JobApi.deleteJobApi,
2022-07-18 19:06:37 +08:00
exportListApi: JobApi.exportJobApi
})
// ========== CRUD 相关 ==========
const actionLoading = ref(false) // 遮罩层
const actionType = ref('') // 操作按钮的类型
const dialogVisible = ref(false) // 是否显示弹出层
const dialogTitle = ref('edit') // 弹出层标题
const formRef = ref<FormExpose>() // 表单 Ref
2022-11-22 17:07:30 +08:00
const detailRef = ref() // 详情 Ref
2022-07-29 01:25:44 +08:00
const cronExpression = ref('')
2022-11-28 23:13:20 +08:00
const nextTimes = ref([])
2022-07-29 01:25:44 +08:00
const shortcuts = ref([
{
text: '每天8点和12点 (自定义追加)',
value: '0 0 8,12 * * ?'
}
])
2022-07-18 19:06:37 +08:00
// 设置标题
const setDialogTile = (type: string) => {
dialogTitle.value = t('action.' + type)
actionType.value = type
dialogVisible.value = true
}
// 新增操作
const handleCreate = () => {
2022-07-29 01:25:44 +08:00
cronExpression.value = ''
2022-07-18 19:06:37 +08:00
setDialogTile('create')
}
2022-11-28 23:13:20 +08:00
2022-11-22 17:07:30 +08:00
// 导出操作
const handleExport = async () => {
await exportList(xGrid, '定时任务.xls')
}
2022-11-28 23:13:20 +08:00
2022-07-18 19:06:37 +08:00
// 修改操作
2022-11-22 17:07:30 +08:00
const handleUpdate = async (rowId: number) => {
2022-07-18 19:06:37 +08:00
setDialogTile('update')
// 设置数据
2022-11-22 17:07:30 +08:00
const res = await JobApi.getJobApi(rowId)
2022-07-29 01:25:44 +08:00
cronExpression.value = res.cronExpression
2022-07-18 19:06:37 +08:00
unref(formRef)?.setValues(res)
}
2022-11-22 17:07:30 +08:00
// 详情操作
const handleDetail = async (rowId: number) => {
// 设置数据
const res = await JobApi.getJobApi(rowId)
detailRef.value = res
2022-11-28 23:13:20 +08:00
// 后续执行时长
const jobNextTime = await JobApi.getJobNextTimesApi(rowId)
nextTimes.value = jobNextTime
2022-11-22 17:07:30 +08:00
setDialogTile('detail')
}
2022-11-28 23:13:20 +08:00
const parseTime = (time) => {
if (!time) {
return null
}
const format = '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if (typeof time === 'string' && /^[0-9]+$/.test(time)) {
time = parseInt(time)
} else if (typeof time === 'string') {
time = time
.replace(new RegExp(/-/gm), '/')
.replace('T', ' ')
.replace(new RegExp(/\.[\d]{3}/gm), '')
}
if (typeof time === 'number' && time.toString().length === 10) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') {
return ['日', '一', '二', '三', '四', '五', '六'][value]
}
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}
2022-11-22 17:07:30 +08:00
// 删除操作
const handleDelete = async (rowId: number) => {
await deleteData(xGrid, rowId)
}
const handleChangeStatus = async (row: JobApi.JobVO) => {
2022-07-29 01:25:44 +08:00
const text = row.status === InfraJobStatusEnum.STOP ? '开启' : '关闭'
const status =
row.status === InfraJobStatusEnum.STOP ? InfraJobStatusEnum.NORMAL : InfraJobStatusEnum.STOP
message
.confirm('确认要' + text + '定时任务编号为"' + row.id + '"的数据项?', t('common.reminder'))
.then(async () => {
row.status =
row.status === InfraJobStatusEnum.NORMAL
? InfraJobStatusEnum.NORMAL
: InfraJobStatusEnum.STOP
await JobApi.updateJobStatusApi(row.id, status)
message.success(text + '成功')
2022-11-22 17:07:30 +08:00
await getList(xGrid)
2022-07-29 01:25:44 +08:00
})
.catch(() => {
row.status =
row.status === InfraJobStatusEnum.NORMAL
? InfraJobStatusEnum.STOP
: InfraJobStatusEnum.NORMAL
})
}
2022-07-18 19:06:37 +08:00
// 执行日志
2022-11-22 17:07:30 +08:00
const handleJobLog = (rowId: number) => {
if (rowId) {
push('/job/job-log?id=' + rowId)
2022-07-18 19:06:37 +08:00
} else {
push('/job/job-log')
}
}
// 执行一次
2022-11-22 17:07:30 +08:00
const handleRun = (row: JobApi.JobVO) => {
2022-07-21 17:42:25 +08:00
message.confirm('确认要立即执行一次' + row.name + '?', t('common.reminder')).then(async () => {
await JobApi.runJobApi(row.id)
message.success('执行成功')
2022-11-22 17:07:30 +08:00
await getList(xGrid)
2022-07-18 19:06:37 +08:00
})
}
// 提交按钮
const submitForm = async () => {
2022-10-17 11:24:22 +08:00
const elForm = unref(formRef)?.getElFormRef()
if (!elForm) return
elForm.validate(async (valid) => {
if (valid) {
actionLoading.value = true
// 提交请求
try {
2022-11-22 17:07:30 +08:00
const data = unref(formRef)?.formModel as JobApi.JobVO
2022-10-17 11:24:22 +08:00
data.cronExpression = cronExpression.value
if (actionType.value === 'create') {
await JobApi.createJobApi(data)
message.success(t('common.createSuccess'))
} else {
await JobApi.updateJobApi(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
} finally {
actionLoading.value = false
2022-11-22 17:07:30 +08:00
await getList(xGrid)
2022-10-17 11:24:22 +08:00
}
2022-07-18 19:06:37 +08:00
}
2022-10-17 11:24:22 +08:00
})
2022-07-18 19:06:37 +08:00
}
</script>