diff --git a/src/types/auto-components.d.ts b/src/types/auto-components.d.ts index 480691fc..80a5900f 100644 --- a/src/types/auto-components.d.ts +++ b/src/types/auto-components.d.ts @@ -23,6 +23,7 @@ declare module '@vue/runtime-core' { DictTag: typeof import('./../components/DictTag/src/DictTag.vue')['default'] Echart: typeof import('./../components/Echart/src/Echart.vue')['default'] Editor: typeof import('./../components/Editor/src/Editor.vue')['default'] + ElAutoResizer: typeof import('element-plus/es')['ElAutoResizer'] ElBadge: typeof import('element-plus/es')['ElBadge'] ElButton: typeof import('element-plus/es')['ElButton'] ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup'] @@ -70,6 +71,7 @@ declare module '@vue/runtime-core' { ElSwitch: typeof import('element-plus/es')['ElSwitch'] ElTable: typeof import('element-plus/es')['ElTable'] ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] + ElTableV2: typeof import('element-plus/es')['ElTableV2'] ElTabPane: typeof import('element-plus/es')['ElTabPane'] ElTabs: typeof import('element-plus/es')['ElTabs'] ElTag: typeof import('element-plus/es')['ElTag'] diff --git a/src/views/infra/job/form.vue b/src/views/infra/job/form.vue index 24488fd7..b50bcacb 100644 --- a/src/views/infra/job/form.vue +++ b/src/views/infra/job/form.vue @@ -107,7 +107,7 @@ const formRules = reactive({ const formRef = ref() // 表单 Ref /** 打开弹窗 */ -const openModal = async (type: string, id?: number) => { +const open = async (type: string, id?: number) => { modelVisible.value = true modelTitle.value = t('action.' + type) formType.value = type @@ -122,7 +122,7 @@ const openModal = async (type: string, id?: number) => { } } } -defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗 +defineExpose({ open }) // 提供 open 方法,用于打开弹窗 /** cron表达式按钮操作 */ const handleShowCron = () => { diff --git a/src/views/infra/job/index.vue b/src/views/infra/job/index.vue index 702b31fe..bc4dfebc 100644 --- a/src/views/infra/job/index.vue +++ b/src/views/infra/job/index.vue @@ -1,19 +1,31 @@ <template> <content-wrap> - <!-- 搜索栏 --> - <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="100px"> + <!-- 搜索工作栏 --> + <el-form + class="-mb-15px" + :model="queryParams" + ref="queryFormRef" + :inline="true" + label-width="100px" + > <el-form-item label="任务名称" prop="name"> <el-input v-model="queryParams.name" placeholder="请输入任务名称" clearable @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> <el-form-item label="任务状态" prop="status"> - <el-select v-model="queryParams.status" placeholder="请选择任务状态" clearable> + <el-select + v-model="queryParams.status" + placeholder="请选择任务状态" + clearable + class="!w-240px" + > <el-option - v-for="dict in getDictOptions(DICT_TYPE.INFRA_JOB_STATUS)" + v-for="dict in getIntDictOptions(DICT_TYPE.INFRA_JOB_STATUS)" :key="dict.value" :label="dict.label" :value="dict.value" @@ -26,6 +38,7 @@ placeholder="请输入处理器的名字" clearable @keyup.enter="handleQuery" + class="!w-240px" /> </el-form-item> <el-form-item> @@ -34,7 +47,7 @@ <el-button type="primary" plain - @click="openModal('create')" + @click="openForm('create')" v-hasPermi="['infra:job:create']" > <Icon icon="ep:plus" class="mr-5px" /> 新增 @@ -48,63 +61,66 @@ > <Icon icon="ep:download" class="mr-5px" /> 导出 </el-button> - <el-button type="info" plain @click="handleJobLog" v-hasPermi="['infra:job:query']"> <Icon icon="ep:zoom-in" class="mr-5px" /> 执行日志 </el-button> </el-form-item> </el-form> + </content-wrap> + <!-- 列表 --> + <content-wrap> <el-table v-loading="loading" :data="list"> <el-table-column label="任务编号" align="center" prop="id" /> <el-table-column label="任务名称" align="center" prop="name" /> <el-table-column label="任务状态" align="center" prop="status"> <template #default="scope"> <dict-tag :type="DICT_TYPE.INFRA_JOB_STATUS" :value="scope.row.status" /> - </template> </el-table-column - >> + </template> + </el-table-column> <el-table-column label="处理器的名字" align="center" prop="handlerName" /> <el-table-column label="处理器的参数" align="center" prop="handlerParam" /> <el-table-column label="CRON 表达式" align="center" prop="cronExpression" /> - <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> + <el-table-column label="操作" align="center" width="200"> <template #default="scope"> <el-button + type="primary" link - icon="el-icon-edit" - @click="openModal('update', scope.row.id)" + @click="openForm('update', scope.row.id)" v-hasPermi="['infra:job:update']" - >修改</el-button > + 修改 + </el-button> <el-button + type="primary" link - icon="el-icon-check" @click="handleChangeStatus(scope.row)" v-hasPermi="['infra:job:update']" - >{{ scope.row.status === InfraJobStatusEnum.STOP ? '开启' : '暂停' }}</el-button > + {{ scope.row.status === InfraJobStatusEnum.STOP ? '开启' : '暂停' }} + </el-button> <el-button + type="danger" link - icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['infra:job:delete']" - >删除</el-button > + 删除 + </el-button> <el-dropdown - class="mt-1" - :teleported="true" @command="(command) => handleCommand(command, scope.row)" v-hasPermi="['infra:job:trigger', 'infra:job:query']" > - <el-button link icon="el-icon-d-arrow-right">更多</el-button> + <el-button type="primary" link><Icon icon="ep:d-arrow-right" /> 更多</el-button> <template #dropdown> <el-dropdown-menu> - <el-dropdown-item command="handleRun" v-if="hasPermi(['infra:job:trigger'])"> + <el-dropdown-item command="handleRun" v-if="checkPermi(['infra:job:trigger'])"> 执行一次 </el-dropdown-item> - <el-dropdown-item command="handleView" v-if="hasPermi(['infra:job:query'])"> + <el-dropdown-item command="handleView" v-if="checkPermi(['infra:job:query'])"> 任务详细 </el-dropdown-item> - <el-dropdown-item command="handleJobLog" v-if="hasPermi(['infra:job:query'])"> + <el-dropdown-item command="handleJobLog" v-if="checkPermi(['infra:job:query'])"> 调度日志 </el-dropdown-item> </el-dropdown-menu> @@ -114,8 +130,7 @@ </el-table-column> </el-table> <!-- 分页组件 --> - <pagination - v-show="total > 0" + <Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @@ -124,23 +139,21 @@ </content-wrap> <!-- 表单弹窗:添加/修改 --> - <job-form ref="modalRef" @success="getList" /> + <job-form ref="formRef" @success="getList" /> <!-- 表单弹窗:查看 --> <job-view ref="viewModalRef" @success="getList" /> </template> - <script setup lang="ts" name="Job"> -import { DICT_TYPE, getDictOptions } from '@/utils/dict' +import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' +import { checkPermi } from '@/utils/permission' import JobForm from './form.vue' import JobView from './view.vue' import download from '@/utils/download' import * as JobApi from '@/api/infra/job' import { InfraJobStatusEnum } from '@/utils/constants' -import { CACHE_KEY, useCache } from '@/hooks/web/useCache' - const { t } = useI18n() // 国际化 const message = useMessage() // 消息弹窗 -const { push } = useRouter() +const { push } = useRouter() // 路由 const loading = ref(true) // 列表的加载中 const total = ref(0) // 列表的总页数 @@ -167,30 +180,6 @@ const getList = async () => { } } -const handleChangeStatus = async (row: JobApi.JobVO) => { - 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 + '成功') - await getList() - }) - .catch(() => { - row.status = - row.status === InfraJobStatusEnum.NORMAL - ? InfraJobStatusEnum.STOP - : InfraJobStatusEnum.NORMAL - }) -} - /** 搜索按钮操作 */ const handleQuery = () => { queryParams.pageNo = 1 @@ -203,10 +192,47 @@ const resetQuery = () => { handleQuery() } +/** 导出按钮操作 */ +const handleExport = async () => { + try { + // 导出的二次确认 + await message.exportConfirm() + // 发起导出 + exportLoading.value = true + const data = await JobApi.exportJobApi(queryParams) + download.excel(data, '定时任务.xls') + } catch { + } finally { + exportLoading.value = false + } +} + /** 添加/修改操作 */ -const modalRef = ref() -const openModal = (type: string, id?: number) => { - modalRef.value.openModal(type, id) +const formRef = ref() +const openForm = (type: string, id?: number) => { + formRef.value.open(type, id) +} + +/** 修改状态操作 */ +const handleChangeStatus = async (row: JobApi.JobVO) => { + try { + // 修改状态的二次确认 + const text = row.status === InfraJobStatusEnum.STOP ? '开启' : '关闭' + await message.confirm( + '确认要' + text + '定时任务编号为"' + row.id + '"的数据项?', + t('common.reminder') + ) + const status = + row.status === InfraJobStatusEnum.STOP ? InfraJobStatusEnum.NORMAL : InfraJobStatusEnum.STOP + await JobApi.updateJobStatusApi(row.id, status) + message.success(text + '成功') + // 刷新列表 + await getList() + } catch { + // 取消后,进行恢复按钮 + row.status = + row.status === InfraJobStatusEnum.NORMAL ? InfraJobStatusEnum.STOP : InfraJobStatusEnum.NORMAL + } } /** 删除按钮操作 */ @@ -222,28 +248,6 @@ const handleDelete = async (id: number) => { } catch {} } -/** 查看操作 */ -const viewModalRef = ref() -const handleView = (rowId?: number) => { - viewModalRef.value.openModal(rowId) -} -// 执行日志 -const handleJobLog = (rowId?: number) => { - if (rowId) { - push('/job/job-log?id=' + rowId) - } else { - push('/job/job-log') - } -} -// 执行一次 -const handleRun = (row: JobApi.JobVO) => { - message.confirm('确认要立即执行一次' + row.name + '?', t('common.reminder')).then(async () => { - await JobApi.runJobApi(row.id) - message.success('执行成功') - await getList() - }) -} - /** '更多'操作按钮 */ const handleCommand = (command, row) => { switch (command) { @@ -261,36 +265,31 @@ const handleCommand = (command, row) => { } } -/** 导出按钮操作 */ -const handleExport = async () => { +/** 执行一次 */ +const handleRun = async (row: JobApi.JobVO) => { try { - // 导出的二次确认 - await message.exportConfirm() - // 发起导出 - exportLoading.value = true - const data = await JobApi.exportJobApi(queryParams) - download.excel(data, '定时任务.xls') - } catch { - } finally { - exportLoading.value = false - } + // 二次确认 + await message.confirm('确认要立即执行一次' + row.name + '?', t('common.reminder')) + // 提交执行 + await JobApi.runJobApi(row.id) + message.success('执行成功') + // 刷新列表 + await getList() + } catch {} } -// 权限判断:dropdown 与 v-hasPermi有冲突会造成大量的waring,改用v-if调用此方法 -const hasPermi = (permiKeys: string[]) => { - const { wsCache } = useCache() - const all_permission = '*:*:*' - const permissions = wsCache.get(CACHE_KEY.USER).permissions - - if (permiKeys && permiKeys instanceof Array && permiKeys.length > 0) { - const permissionFlag = permiKeys - - const hasPermissions = permissions.some((permission: string) => { - return all_permission === permission || permissionFlag.includes(permission) - }) - return hasPermissions +/** 查看操作 */ +const viewModalRef = ref() +const handleView = (rowId?: number) => { + viewModalRef.value.openForm(rowId) +} +// 执行日志 +const handleJobLog = (rowId?: number) => { + if (rowId) { + push('/job/job-log?id=' + rowId) + } else { + push('/job/job-log') } - return false } /** 初始化 **/ diff --git a/src/views/infra/job/utils.ts b/src/views/infra/job/utils.ts deleted file mode 100644 index a3774f22..00000000 --- a/src/views/infra/job/utils.ts +++ /dev/null @@ -1,44 +0,0 @@ -export 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 -} diff --git a/src/views/infra/job/view.vue b/src/views/infra/job/view.vue index d195e0e3..c30e235a 100644 --- a/src/views/infra/job/view.vue +++ b/src/views/infra/job/view.vue @@ -40,7 +40,7 @@ </template> <script setup lang="ts" name="JobView"> import * as JobApi from '@/api/infra/job' -import { parseTime } from './utils' +import { parseTime } from '@/utils/formatTime' import { DICT_TYPE } from '@/utils/dict' const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 diff --git a/src/views/system/errorCode/index.vue b/src/views/system/errorCode/index.vue index c95d652c..e94b00f0 100644 --- a/src/views/system/errorCode/index.vue +++ b/src/views/system/errorCode/index.vue @@ -121,8 +121,7 @@ </el-table-column> </el-table> <!-- 分页组件 --> - <pagination - v-show="total > 0" + <Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue index 19990ca9..b0f7f964 100644 --- a/src/views/system/user/index.vue +++ b/src/views/system/user/index.vue @@ -137,7 +137,7 @@ <Icon icon="ep:edit" />修改 </el-button> <el-dropdown - @command="(command) => handleCommand(command, scope.$index, scope.row)" + @command="(command) => handleCommand(command, scope.row)" v-hasPermi="[ 'system:user:delete', 'system:user:update-password', @@ -147,22 +147,24 @@ <el-button type="primary" link><Icon icon="ep:d-arrow-right" /> 更多</el-button> <template #dropdown> <el-dropdown-menu> - <!-- div包住避免控制台报错:Runtime directive used on component with non-element root node --> - <div v-hasPermi="['system:user:delete']"> - <el-dropdown-item command="handleDelete"> - <Icon icon="ep:delete" />删除 - </el-dropdown-item> - </div> - <div v-hasPermi="['system:user:update-password']"> - <el-dropdown-item command="handleResetPwd"> - <Icon icon="ep:key" />重置密码 - </el-dropdown-item> - </div> - <div v-hasPermi="['system:permission:assign-user-role']"> - <el-dropdown-item command="handleRole"> - <Icon icon="ep:circle-check" />分配角色 - </el-dropdown-item> - </div> + <el-dropdown-item + command="handleDelete" + v-if="checkPermi(['system:user:delete'])" + > + <Icon icon="ep:delete" />删除 + </el-dropdown-item> + <el-dropdown-item + command="handleResetPwd" + v-if="checkPermi(['system:user:update-password'])" + > + <Icon icon="ep:key" />重置密码 + </el-dropdown-item> + <el-dropdown-item + command="handleRole" + v-if="checkPermi(['system:permission:assign-user-role'])" + > + <Icon icon="ep:circle-check" />分配角色 + </el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> @@ -189,6 +191,7 @@ </template> <script setup lang="ts" name="User"> import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' +import { checkPermi } from '@/utils/permission' import { dateFormatter } from '@/utils/formatTime' import download from '@/utils/download' import { CommonStatusEnum } from '@/utils/constants' @@ -290,8 +293,7 @@ const handleExport = async () => { } /** 操作分发 */ -const handleCommand = (command: string, index: number, row: UserApi.UserVO) => { - console.log(index) +const handleCommand = (command: string, row: UserApi.UserVO) => { switch (command) { case 'handleDelete': handleDelete(row.id)