<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="renderer" content="webkit"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" href="favicon.ico"> <title>é’æ²³åŽ¿è¨å°”托海智慧水务系统</title> <link rel="stylesheet" href="css/main.css" /> <link rel="stylesheet" href="js/lib/element-plus/index.css" /> <script src="js/lib/vue.global.js"></script> <script src="js/lib/element-plus/element-plus.js"></script> <script src="js/lib/element-plus/icons-vue.js"></script> <script src="js/lib/axios.min.js"></script> <script src="js/lib/httpVueLoader.js"></script> </head> <body> <div id="app"> <div id="loader-wrapper" v-if="loading"> <div id="loader"></div> <div class="loader-section section-left"></div> <div class="loader-section section-right"></div> <div class="load_title">æ£åœ¨åŠ è½½ç³»ç»Ÿèµ„æºï¼Œè¯·è€å¿ƒç‰å¾…</div> </div> <el-form :model="queryParams" :inline="true"> <el-form-item label="任务编å·"> <el-input v-model="queryParams.taskNo" placeholder="请输入任务编å·" clearable style="width: 200px" @keyup.enter="handleQuery" /> </el-form-item> <el-form-item label="任务åç§°"> <el-input v-model="queryParams.keywords" placeholder="请输入任务åç§°" clearable style="width: 200px" @keyup.enter="handleQuery" /> </el-form-item> <el-form-item label="任务状æ€"> <el-select v-model="queryParams.listStatus" multiple placeholder="请选择" style="width: 240px" > <el-option v-for="item in listEState" :key="item.value" :label="item.label" :value="item.value" /> </el-select> </el-form-item> <el-form-item label="创建时间"> <el-date-picker v-model="dateRangeCreateTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="ç»“æŸæ—¥æœŸ" :default-time="[ new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59), ]" ></el-date-picker> </el-form-item> <el-form-item> <el-button type="primary" icon="search" @click="handleQuery">æœç´¢</el-button> <el-button icon="Refresh" @click="resetQuery">é‡ç½®</el-button> </el-form-item> </el-form> <el-row :gutter="10" class="mb8"> <el-col :span="1.5"> <el-button type="primary" plain icon="Plus" @click="handleAdd" >新增</el-button > </el-col> </el-row> <el-table :stripe="true" :border="true" :data="dataList" @selection-change="handleSelectionChange" @row-dblclick="handleDetail" > <el-table-column label="任务编å·" min-width="175" align="center" prop="taskNo"></el-table-column> <el-table-column label="任务åç§°" min-width="300" align="center" prop="taskName"></el-table-column> <el-table-column label="执行频率cron" min-width="110" align="center" prop="schedulerRule"></el-table-column> <el-table-column label="执行器åç§°" min-width="200" align="center" prop="executor"></el-table-column> <el-table-column label="任务状æ€" min-width="80" align="center" prop="status"> <template #default="scope"> {{ getEStateLabel(scope.row.status) }} </template> </el-table-column> <el-table-column label="创建时间" min-width="155" align="center" prop="createTimeView"></el-table-column> <el-table-column label="最åŽä¿®æ”¹æ—¶é—´" align="center" min-width="185" prop="updateTimeView"></el-table-column> <el-table-column label="æ“作" align="center" min-width="220" fixed="right" class-name="small-padding fixed-width" > <template #default="scope"> <el-button link type="primary" @click="handleDetail(scope.row)" >详情</el-button> <el-button link type="warning" @click="handleListRecord(scope.row)" >执行记录</el-button> <el-dropdown style="margin-left:10px;"> <el-button size="small" type="danger"> <span style="padding:0px 8px;">æ“作</span><el-icon class="el-icon--right"><arrow-down /></el-icon> </el-button> <template #dropdown> <el-dropdown-menu> <el-dropdown-item @click="handleUpdate(scope.row)">修改</el-dropdown-item> <el-dropdown-item @click="handleEnable(scope.row)" v-if="scope.row.status === 2">打开</el-dropdown-item> <el-dropdown-item @click="handleStop(scope.row)" v-if="scope.row.status === 1">å…³é—</el-dropdown-item> <el-dropdown-item @click="handleRunNow(scope.row)">ç«‹å³æ‰§è¡Œ</el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> </template> </el-table-column> </el-table> <el-pagination v-if="total > 0" :background="tabConfig.background" :hide-on-single-page="tabConfig.hideOnSinglePage" :page-sizes="tabConfig.listPageSize" :total="total" v-model:current-page="queryParams.page" v-model:page-size="queryParams.limit" @change ="getList" ></el-pagination> <!-- æ·»åŠ å¯¹è¯æ¡† --> <el-dialog title="æ·»åŠ ä»»åŠ¡" v-model="dialogOpenCreate" width="750px" append-to-body > <el-form :model="formCreate" label-width="125px" > <el-form-item label="任务åç§°" prop="taskName"> <el-input v-model="formCreate.taskName" placeholder="" /> </el-form-item> <el-form-item label="定时器ç–ç•¥" prop="schedulerRule"> <el-input v-model="formCreate.schedulerRule" placeholder="" clearable> <template #append> <el-tooltip content="é…置定时器ç–ç•¥" placement="top"> <el-button type="success" icon="Edit" @click="() => { showCreateCronCore = !showCreateCronCore }" /> </el-tooltip> </template> </el-input> </el-form-item> <el-form-item label="执行器åç§°" prop="executor"> <el-input v-model="formCreate.executor" placeholder="" /> </el-form-item> <el-form-item label="æ‰§è¡Œå‚æ•°" prop="executeParameter"> <el-input v-model="formCreate.executeParameter" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" placeholder="" /> </el-form-item> <el-form-item label="通知方å¼" prop="sendType"> <el-select v-model="formCreate.sendType" collapse-tags collapse-tags-tooltip placeholder="请选择" style="width: 240px" > <el-option label="Http" value="1"/> </el-select> </el-form-item> <el-form-item label="通知地å€" prop="url"> <el-input v-model="formCreate.url" placeholder="" /> </el-form-item> </el-form> <template #footer> <div class="dialog-footer"> <el-button :loading="createLoading" type="primary" @click="submitCreate" >ç¡® 定</el-button> <el-button @click="cancelCreate">å– æ¶ˆ</el-button> </div> </template> </el-dialog> <!-- ä¿®æ”¹å¯¹è¯æ¡† --> <el-dialog :title="title" v-model="dialogOpenModify" width="750px" append-to-body > <el-form :disabled="isDetail" :model="formModify" label-width="125px" > <el-form-item label="任务编å·" prop="taskNo"> <el-input v-model="formModify.id" type="hidden" /> {{ formModify.taskNo }} </el-form-item> <el-form-item label="任务åç§°" prop="taskName"> <el-input v-model="formModify.taskName" placeholder="" /> </el-form-item> <el-form-item label="定时器ç–ç•¥" prop="schedulerRule"> <el-input v-model="formModify.schedulerRule" placeholder="" clearable> <template #append> <el-tooltip content="é…置定时器ç–ç•¥" placement="top"> <el-button type="success" icon="Edit" @click="() => { showModifyCronCore = !showModifyCronCore }" /> </el-tooltip> </template> </el-input> </el-form-item> <el-form-item label="执行器åç§°" prop="executor"> <el-input v-model="formModify.executor" placeholder="" /> </el-form-item> <el-form-item label="æ‰§è¡Œå‚æ•°" prop="executeParameter"> <el-input v-model="formModify.executeParameter" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" placeholder="" /> </el-form-item> <el-form-item label="状æ€" prop="status"> <el-radio-group v-model="formModify.status"> <el-radio :label="1">å¼€å¯</el-radio> <el-radio :label="2">å…³é—</el-radio> </el-radio-group> </el-form-item> <el-form-item label="通知方å¼" prop="sendType"> <el-select v-model="formModify.sendType" collapse-tags collapse-tags-tooltip placeholder="请选择" style="width: 240px" > <el-option label="Http" value="1"/> </el-select> </el-form-item> <el-form-item label="通知地å€" prop="url"> <el-input v-model="formModify.url" placeholder="" /> </el-form-item> <el-form-item label="创建时间" prop="createTimeView"> {{ formModify.createTimeView }} </el-form-item> <el-form-item label="æ›´æ–°æ—¶é—´" prop="updateTimeView"> {{ formModify.updateTimeView }} </el-form-item> </el-form> <template #footer> <div class="dialog-footer"> <el-button v-if="isDetail === false" :loading="modifyLoading" type="primary" @click="submitModify" >ç¡® 定</el-button> <el-button @click="cancelModify">{{ cancelModifyTxt }}</el-button> <el-button type="primary" v-if="isDetail" @click="changeModify" >ç¼– 辑</el-button> </div> </template> </el-dialog> <!-- ç«‹å³æ‰§è¡Œå¯¹è¯æ¡† --> <el-dialog :title="title" v-model="dialogOpenRunNow" width="450px" append-to-body > <el-form :model="formRunNow" label-width="80px" > <el-form-item label="æ‰§è¡Œå‚æ•°" prop="executeParameter"> <el-input v-model="formRunNow.id" type="hidden"></el-input> <el-input v-model="formRunNow.executeParameter" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" placeholder="" ></el-input> </el-form-item> </el-form> <template #footer> <div class="dialog-footer"> <el-button :loading="runNowLoading" type="primary" @click="submitRunNow" >ç¡® 定</el-button> <el-button @click="cancelRunNow">å– æ¶ˆ</el-button> </div> </template> </el-dialog> <!-- æ‰§è¡Œè®°å½•å¯¹è¯æ¡† --> <el-dialog title="执行记录" v-model="dialogOpenJobRecord" :fullscreen="true" :close-on-click-modal="false" :destroy-on-close="true" append-to-body > <!-- è®¾ç½®å¯¹è¯æ¡†å†…容高度 --> <div style="height:75vh;"> <el-scrollbar> <iframe :src="jobRecordUrl" id="map" scrolling="no" frameborder="0" style="width:100%;height:100%;position:absolute;top:4px;left:10px;right:0px;bottom:10px;"></iframe> </el-scrollbar> </div> </el-dialog> <!-- cron表达å¼å¯¹è¯æ¡† --> <el-dialog title="定时ç–ç•¥" v-model="showCreateCronCore" width="600px" append-to-body > <!-- <vue3-cron @change="onCreateChangeCron" v-if="showCreateCronCore" v-model:value="formCreate.schedulerRule" @close="showCreateCronCore = false" /> --> <crontab @hide="showCreateCronCore = false" @fill="onCreateChangeCron" :expression="formCreate.schedulerRule" /> </el-dialog> <el-dialog title="定时ç–ç•¥" v-model="showModifyCronCore" width="600px" append-to-body > <!-- <vue3-cron @change="onCreateChangeCron" v-if="showModifyCronCore" v-model:value="formModify.schedulerRule" @close="showModifyCronCore = false" /> --> <crontab @hide="showModifyCronCore = false" @fill="onModifyChangeCron" :expression="formModify.schedulerRule" /> </el-dialog> </div> <script type="module"> import { EState } from "/js/enums.js" const { createApp, ref, onMounted, h } = Vue const Http = axios.create({ baseURL: location.pathname.substr(0, location.pathname.lastIndexOf('/')), timeout: 1000, headers: {'X-Custom-Header': 'foobar'} }); const $message = ElementPlus.ElMessage; const $confirm = ElementPlus.ElMessageBox; var app = Vue.createApp({ el: '#app', // 相对路径引用å‚考 components: { 'job-record': httpVueLoader('./job-record.vue'), 'crontab': httpVueLoader('./components/vue3-cron.vue') }, data() { return { recordConfig: { close_on_click_modal: false, destroy_on_close: true } } }, methods: { }, mounted: () => { //$message('è¿™æ˜¯ä¸€æ¡æ™®é€šinfo消æ¯'); }, setup() { const tabConfig = ref({ background: true, hideOnSinglePage: true, listPageSize: [20, 50, 100, 200] }); const showCreateCronCore = ref(false); // æ˜¯å¦æ‰“å¼€cron表达å¼é…置框 const onCreateChangeCron = (val) => { if (typeof val !== "string") { return false } formCreate.value.schedulerRule = val; }; const showModifyCronCore = ref(false); // æ˜¯å¦æ‰“å¼€cron表达å¼é…置框 const onModifyChangeCron = (val) => { if (typeof val !== "string") { return false } formModify.value.schedulerRule = val; }; const listEState = EState.enums; const getEStateLabel = (value) => { return EState.getLabelByValue(value) } const loading = ref(true) const dataList = ref([]); const createLoading = ref(false); const dialogOpenCreate = ref(false); const modifyLoading = ref(false); const dialogOpenModify = ref(false); const runNowLoading = ref(false); const dialogOpenRunNow = ref(false); const total = ref(0); const dateRangeCreateTime = ref([]); const ids = ref([]); const single = ref(true); const multiple = ref(true); const title = ref(""); const cancelModifyTxt = ref("å– æ¶ˆ"); const isDetail = ref(false); const jobRecordTaskNo = ref(""); const dialogOpenJobRecord = ref(false); const jobRecordUrl = ref(""); const queryParams = ref({ page: 1, limit: 10, createTimeRange: '', keywords: '', listStatus: [], createTime: '', taskNo: '' }); const formCreate = ref({}); const formModify = ref({}); const formRunNow = ref({ id: 0, executeParameter: "", }); const rulesRunNow = ref({ //executeParameter: [{ required: true, message: "巡更人员列表ä¸èƒ½ä¸ºç©º", trigger: "blur" }] }); /** 查询列表 */ function getList() { loading.value = true; if ( dateRangeCreateTime && dateRangeCreateTime.value && dateRangeCreateTime.value[0] ) { queryParams.value.createTimeRange = dateRangeCreateTime.value.join(" ~ "); } Http.post('/quartz/listTask', queryParams.value) .then((response) => { let data = response.data.data; dataList.value = data.list; total.value = data.total; loading.value = false; }); } /** æœç´¢æŒ‰é’®æ“作 */ function handleQuery() { queryParams.value.page = 1; getList(); } /** é‡ç½®æŒ‰é’®æ“作 */ function resetQuery() { dateRangeCreateTime.value = []; queryParams.value = { page: 1, limit: 10, createTimeRange: "", keywords: undefined, listStatus: undefined, createTime: undefined, taskNo: undefined }; handleQuery(); } /** é€‰æ‹©æ¡æ•° */ function handleSelectionChange(selection) { console.log('handleSelectionChange' + selection); ids.value = selection.map((item) => item.id); single.value = selection.length != 1; multiple.value = !selection.length; } /** å–æ¶ˆæ–°å¢žæŒ‰é’® */ function cancelCreate() { dialogOpenCreate.value = false; resetCreate(); } /** 新增表å•é‡ç½® */ function resetCreate() { formCreate.value = { taskName: undefined, schedulerRule: undefined, executor: undefined, sendType: undefined, url: undefined, executeParameter: undefined, }; } /** 新增按钮 */ function handleAdd() { resetCreate(); dialogOpenCreate.value = true; title.value = "æ·»åŠ ä»»åŠ¡"; } /** 新增æäº¤ */ function submitCreate() { let _self = this; createLoading.value = true; Http.post('/quartz/addTask', formCreate.value) .then((response) => { $message.success('新增æˆåŠŸ'); dialogOpenCreate.value = false; getList(); }) .finally(() => { createLoading.value = false; }); } /** 详情按钮 */ function handleDetail(row) { modifyLoading.value = true; resetModify(); const id = row.id || ids.value[0]; isDetail.value = true; modifyLoading.value = false; formModify.value = {...row}; dialogOpenModify.value = true; title.value = "任务信æ¯"; cancelModifyTxt.value = "å…³ é—"; console.log('handleDetail: ' + JSON.stringify(formModify.value)) } /** 详情编辑 */ function changeModify() { isDetail.value = false; title.value = "修改任务"; } /** 编辑表å•é‡ç½® */ function resetModify() { formModify.value = { id: undefined, taskName: undefined, schedulerRule: undefined, executor: undefined, sendType: undefined, url: undefined, executeParameter: undefined, }; } /** å–æ¶ˆç¼–辑按钮 */ function cancelModify() { dialogOpenModify.value = false; resetModify(); } /** 修改按钮 */ function handleUpdate(row) { modifyLoading.value = true; resetModify(); const id = row.id || ids.value[0]; isDetail.value = false; modifyLoading.value = false; formModify.value = {...row}; dialogOpenModify.value = true; title.value = "修改任务"; cancelModifyTxt.value = "å– æ¶ˆ"; console.log('handleUpdate: ' + JSON.stringify(formModify.value)) } /** 修改æäº¤ */ function submitModify() { let _self = this; modifyLoading.value = true; console.log($message) Http.post('/quartz/editTask', formModify.value) .then((response) => { $message.success('修改æˆåŠŸ'); dialogOpenModify.value = false; getList(); }) .finally(() => { modifyLoading.value = false; }); } /** åœç”¨æŒ‰é’® */ function handleStop(row) { $confirm.confirm( '确定è¦å…³é—å—?', 'Warning', { confirmButtonText: '确认', cancelButtonText: 'å–æ¶ˆ', type: 'warning', } ) .then(() => { loading.value = true; const id = row.id; Http.post('/quartz/optionJob/' + id, {}).then((response) => { // 调用列表查询 getList(); }) .finally(() => { loading.value = false; }); }) .catch(() => { $message.info('æ“ä½œå–æ¶ˆ') }) } /** å¯ç”¨æŒ‰é’® */ function handleEnable(row) { $confirm.confirm( '确定è¦å¼€å¯å—?', 'Warning', { confirmButtonText: '确认', cancelButtonText: 'å–æ¶ˆ', type: 'warning', } ) .then(() => { loading.value = true; const id = row.id; Http.post('/quartz/optionJob/' + id, {}).then((response) => { // 调用列表查询 getList(); }) .finally(() => { loading.value = false; }); }) .catch(() => { $message.info('æ“ä½œå–æ¶ˆ') }) } /** ç«‹å³æ‰§è¡ŒæŒ‰é’® */ function handleRunNow(row) { console.log('handleRunNow: ' + JSON.stringify(row)) dialogOpenRunNow.value = true; formRunNow.value.id = row.id; formRunNow.value.executeParameter = row.executeParameter; title.value = "执行任务"; } /** å–æ¶ˆæ“作按钮 */ function cancelRunNow() { dialogOpenRunNow.value = false; } /** æäº¤æ“作 */ function submitRunNow() { runNowLoading.value = true; Http.post('/quartz/runTaskRightNow', formRunNow.value).then((response) => { dialogOpenRunNow.value = false; // 调用列表查询 getList(); }) .finally(() => { runNowLoading.value = false; }); } /** 执行记录 */ function handleListRecord(row) { dialogOpenJobRecord.value = true; jobRecordTaskNo.value = row.taskNo; jobRecordUrl.value= '/job-record.html?taskNo=' + row.taskNo; } onMounted(() => { loading.value = false handleQuery() }) return { tabConfig, listEState, getEStateLabel, showCreateCronCore, onCreateChangeCron, showModifyCronCore, onModifyChangeCron, loading, dataList, createLoading, dialogOpenCreate, modifyLoading, dialogOpenModify, runNowLoading, dialogOpenRunNow, total, dateRangeCreateTime, ids, single, multiple, title, cancelModifyTxt, isDetail, jobRecordTaskNo, dialogOpenJobRecord, jobRecordUrl, queryParams, formCreate, formModify, formRunNow, getList, handleQuery, resetQuery, handleSelectionChange, cancelCreate, resetCreate, handleAdd, submitCreate, handleDetail, changeModify, resetModify, cancelModify, handleUpdate, submitModify, handleStop, handleEnable, handleRunNow, cancelRunNow, submitRunNow, handleListRecord } } }) app.use(httpVueLoader) app.use(ElementPlus) for (const [key, component] of Object.entries(ElementPlusIconsVue)) { app.component(key, component) } app.mount("#app") </script> </body> </html>