index.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. <template>
  2. <content-wrap>
  3. <!-- 搜索栏 -->
  4. <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="100px">
  5. <el-form-item label="任务名称" prop="name">
  6. <el-input
  7. v-model="queryParams.name"
  8. placeholder="请输入任务名称"
  9. clearable
  10. @keyup.enter="handleQuery"
  11. />
  12. </el-form-item>
  13. <el-form-item label="任务状态" prop="status">
  14. <el-select v-model="queryParams.status" placeholder="请选择任务状态" clearable>
  15. <el-option
  16. v-for="dict in getDictOptions(DICT_TYPE.INFRA_JOB_STATUS)"
  17. :key="dict.value"
  18. :label="dict.label"
  19. :value="dict.value"
  20. />
  21. </el-select>
  22. </el-form-item>
  23. <el-form-item label="处理器的名字" prop="handlerName">
  24. <el-input
  25. v-model="queryParams.handlerName"
  26. placeholder="请输入处理器的名字"
  27. clearable
  28. @keyup.enter="handleQuery"
  29. />
  30. </el-form-item>
  31. <el-form-item>
  32. <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
  33. <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
  34. <el-button
  35. type="primary"
  36. plain
  37. @click="openModal('create')"
  38. v-hasPermi="['infra:job:create']"
  39. >
  40. <Icon icon="ep:plus" class="mr-5px" /> 新增
  41. </el-button>
  42. <el-button
  43. type="success"
  44. plain
  45. @click="handleExport"
  46. :loading="exportLoading"
  47. v-hasPermi="['infra:job:export']"
  48. >
  49. <Icon icon="ep:download" class="mr-5px" /> 导出
  50. </el-button>
  51. <el-button type="info" plain @click="handleJobLog" v-hasPermi="['infra:job:query']">
  52. <Icon icon="ep:zoom-in" class="mr-5px" /> 执行日志
  53. </el-button>
  54. </el-form-item>
  55. </el-form>
  56. <el-table v-loading="loading" :data="list">
  57. <el-table-column label="任务编号" align="center" prop="id" />
  58. <el-table-column label="任务名称" align="center" prop="name" />
  59. <el-table-column label="任务状态" align="center" prop="status">
  60. <template #default="scope">
  61. <dict-tag :type="DICT_TYPE.INFRA_JOB_STATUS" :value="scope.row.status" />
  62. </template> </el-table-column
  63. >>
  64. <el-table-column label="处理器的名字" align="center" prop="handlerName" />
  65. <el-table-column label="处理器的参数" align="center" prop="handlerParam" />
  66. <el-table-column label="CRON 表达式" align="center" prop="cronExpression" />
  67. <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  68. <template #default="scope">
  69. <el-button
  70. link
  71. icon="el-icon-edit"
  72. @click="openModal('update', scope.row.id)"
  73. v-hasPermi="['infra:job:update']"
  74. >修改</el-button
  75. >
  76. <el-button
  77. link
  78. icon="el-icon-check"
  79. @click="handleChangeStatus(scope.row)"
  80. v-hasPermi="['infra:job:update']"
  81. >{{ scope.row.status === InfraJobStatusEnum.STOP ? '开启' : '暂停' }}</el-button
  82. >
  83. <el-button
  84. link
  85. icon="el-icon-delete"
  86. @click="handleDelete(scope.row)"
  87. v-hasPermi="['infra:job:delete']"
  88. >删除</el-button
  89. >
  90. <el-dropdown
  91. class="mt-1"
  92. :teleported="true"
  93. @command="(command) => handleCommand(command, scope.row)"
  94. v-hasPermi="['infra:job:trigger', 'infra:job:query']"
  95. >
  96. <el-button link icon="el-icon-d-arrow-right">更多</el-button>
  97. <template #dropdown>
  98. <el-dropdown-menu>
  99. <el-dropdown-item command="handleRun" v-if="hasPermi(['infra:job:trigger'])">
  100. 执行一次
  101. </el-dropdown-item>
  102. <el-dropdown-item command="handleView" v-if="hasPermi(['infra:job:query'])">
  103. 任务详细
  104. </el-dropdown-item>
  105. <el-dropdown-item command="handleJobLog" v-if="hasPermi(['infra:job:query'])">
  106. 调度日志
  107. </el-dropdown-item>
  108. </el-dropdown-menu>
  109. </template>
  110. </el-dropdown>
  111. </template>
  112. </el-table-column>
  113. </el-table>
  114. <!-- 分页组件 -->
  115. <pagination
  116. v-show="total > 0"
  117. :total="total"
  118. v-model:page="queryParams.pageNo"
  119. v-model:limit="queryParams.pageSize"
  120. @pagination="getList"
  121. />
  122. </content-wrap>
  123. <!-- 表单弹窗:添加/修改 -->
  124. <job-form ref="modalRef" @success="getList" />
  125. <!-- 表单弹窗:查看 -->
  126. <job-view ref="viewModalRef" @success="getList" />
  127. </template>
  128. <script setup lang="ts" name="Job">
  129. import { DICT_TYPE, getDictOptions } from '@/utils/dict'
  130. import JobForm from './form.vue'
  131. import JobView from './view.vue'
  132. import download from '@/utils/download'
  133. import * as JobApi from '@/api/infra/job'
  134. import { InfraJobStatusEnum } from '@/utils/constants'
  135. import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
  136. const { t } = useI18n() // 国际化
  137. const message = useMessage() // 消息弹窗
  138. const { push } = useRouter()
  139. const loading = ref(true) // 列表的加载中
  140. const total = ref(0) // 列表的总页数
  141. const list = ref([]) // 列表的数据
  142. const queryParams = reactive({
  143. pageNo: 1,
  144. pageSize: 10,
  145. name: undefined,
  146. status: undefined,
  147. handlerName: undefined
  148. })
  149. const queryFormRef = ref() // 搜索的表单
  150. const exportLoading = ref(false) // 导出的加载中
  151. /** 查询参数列表 */
  152. const getList = async () => {
  153. loading.value = true
  154. try {
  155. const data = await JobApi.getJobPageApi(queryParams)
  156. list.value = data.list
  157. total.value = data.total
  158. } finally {
  159. loading.value = false
  160. }
  161. }
  162. const handleChangeStatus = async (row: JobApi.JobVO) => {
  163. const text = row.status === InfraJobStatusEnum.STOP ? '开启' : '关闭'
  164. const status =
  165. row.status === InfraJobStatusEnum.STOP ? InfraJobStatusEnum.NORMAL : InfraJobStatusEnum.STOP
  166. message
  167. .confirm('确认要' + text + '定时任务编号为"' + row.id + '"的数据项?', t('common.reminder'))
  168. .then(async () => {
  169. row.status =
  170. row.status === InfraJobStatusEnum.NORMAL
  171. ? InfraJobStatusEnum.NORMAL
  172. : InfraJobStatusEnum.STOP
  173. await JobApi.updateJobStatusApi(row.id, status)
  174. message.success(text + '成功')
  175. await getList()
  176. })
  177. .catch(() => {
  178. row.status =
  179. row.status === InfraJobStatusEnum.NORMAL
  180. ? InfraJobStatusEnum.STOP
  181. : InfraJobStatusEnum.NORMAL
  182. })
  183. }
  184. /** 搜索按钮操作 */
  185. const handleQuery = () => {
  186. queryParams.pageNo = 1
  187. getList()
  188. }
  189. /** 重置按钮操作 */
  190. const resetQuery = () => {
  191. queryFormRef.value.resetFields()
  192. handleQuery()
  193. }
  194. /** 添加/修改操作 */
  195. const modalRef = ref()
  196. const openModal = (type: string, id?: number) => {
  197. modalRef.value.openModal(type, id)
  198. }
  199. /** 删除按钮操作 */
  200. const handleDelete = async (id: number) => {
  201. try {
  202. // 删除的二次确认
  203. await message.delConfirm()
  204. // 发起删除
  205. await JobApi.deleteJobApi(id)
  206. message.success(t('common.delSuccess'))
  207. // 刷新列表
  208. await getList()
  209. } catch {}
  210. }
  211. /** 查看操作 */
  212. const viewModalRef = ref()
  213. const handleView = (rowId?: number) => {
  214. viewModalRef.value.openModal(rowId)
  215. }
  216. // 执行日志
  217. const handleJobLog = (rowId?: number) => {
  218. if (rowId) {
  219. push('/job/job-log?id=' + rowId)
  220. } else {
  221. push('/job/job-log')
  222. }
  223. }
  224. // 执行一次
  225. const handleRun = (row: JobApi.JobVO) => {
  226. message.confirm('确认要立即执行一次' + row.name + '?', t('common.reminder')).then(async () => {
  227. await JobApi.runJobApi(row.id)
  228. message.success('执行成功')
  229. await getList()
  230. })
  231. }
  232. /** '更多'操作按钮 */
  233. const handleCommand = (command, row) => {
  234. switch (command) {
  235. case 'handleRun':
  236. handleRun(row)
  237. break
  238. case 'handleView':
  239. handleView(row?.id)
  240. break
  241. case 'handleJobLog':
  242. handleJobLog(row?.id)
  243. break
  244. default:
  245. break
  246. }
  247. }
  248. /** 导出按钮操作 */
  249. const handleExport = async () => {
  250. try {
  251. // 导出的二次确认
  252. await message.exportConfirm()
  253. // 发起导出
  254. exportLoading.value = true
  255. const data = await JobApi.exportJobApi(queryParams)
  256. download.excel(data, '定时任务.xls')
  257. } catch {
  258. } finally {
  259. exportLoading.value = false
  260. }
  261. }
  262. // 权限判断:dropdown 与 v-hasPermi有冲突会造成大量的waring,改用v-if调用此方法
  263. const hasPermi = (permiKeys: string[]) => {
  264. const { wsCache } = useCache()
  265. const all_permission = '*:*:*'
  266. const permissions = wsCache.get(CACHE_KEY.USER).permissions
  267. if (permiKeys && permiKeys instanceof Array && permiKeys.length > 0) {
  268. const permissionFlag = permiKeys
  269. const hasPermissions = permissions.some((permission: string) => {
  270. return all_permission === permission || permissionFlag.includes(permission)
  271. })
  272. return hasPermissions
  273. }
  274. return false
  275. }
  276. /** 初始化 **/
  277. onMounted(() => {
  278. getList()
  279. })
  280. </script>