queue.html 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. <template>
  2. <el-card shadow="never">
  3. <template #header>
  4. <el-alert effect="dark" :closable="false" title="使用说明">任务队列为异步执行,通常用于定时任务,循环任务,发送消息等,让队列任务与主业务进行解耦,使其不阻塞主业务的操作</el-alert>
  5. </template>
  6. <el-form label-width="120px" label-position="top">
  7. <el-form-item label="{:__('服务状态')}:">
  8. <el-alert style="margin-bottom:10px;" type="warning">
  9. 如果服务启动不成功,请在根目录下手动执行命令:<el-tag style="margin:0 10px;">php think Queue</el-tag>linux环境下使用nohup让服务在后台运行<el-tag style="margin:0 10px;">nohup php think Queue > queue.log &</el-tag>windows环境下请勿关闭进程窗口。
  10. </el-alert>
  11. <div class="status" v-if="!status">
  12. <i class="fa fa-spinner fa-spin"></i>
  13. <span style="margin-left: 5px;">服务检测中..</span>
  14. </div>
  15. <div class="status" v-if="status == 'normal'">
  16. <el-tag type="success">{:__('正常运行')}</el-tag>
  17. <span style="margin-left: 30px;margin-right: 30px;">运行时长:{{parseTime(keeptime)}}</span>
  18. <el-button size="small" type="danger" @click="changeStatus(0)">停止运行</el-button>
  19. </div>
  20. <div class="status" v-if="status == 'hidden'">
  21. <el-tag type="info">{:__('已经停止')}</el-tag>
  22. <span style="margin-left: 30px;margin-right: 30px;">停止时间:{{stoptime}}</span>
  23. <el-button size="small" type="success" @click="changeStatus(1)">启动服务</el-button>
  24. </div>
  25. </el-form-item>
  26. <el-divider></el-divider>
  27. <el-form-item label="{:__('添加任务')}:">
  28. <el-alert style="margin-bottom:10px;" type="warning">添加新任务需要完成一个处理类,该处理类实现了接口<el-tag>app\admin\command\queueEvent\EventInterFace</el-tag>接口。</el-alert>
  29. <el-button type="success" size="small" @click="addEvent">{:__('添加')}</el-button>
  30. </el-form-item>
  31. <el-divider></el-divider>
  32. <el-form-item label="{:__('当前任务')}:">
  33. <el-alert style="margin-bottom:10px;" type="warning">运行中的任务,每5分钟刷新一次。</el-alert>
  34. <el-table :data="eventList" style="width: 100%">
  35. <el-table-column prop="title" label="{:__('任务名称')}"></el-table-column>
  36. <el-table-column prop="function" label="{:__('处理类')}"></el-table-column>
  37. <el-table-column label="{:__('任务类型')}">
  38. <template #default="{row}">
  39. <el-tag v-if="row.limit == 0">{:__('循环任务')}</el-tag>
  40. <el-tag v-else type="warning">{:__('定时任务')}-{{row.limit}}{:__('次')}</el-tag>
  41. </template>
  42. </el-table-column>
  43. <el-table-column prop="times" label="{:__('已执行次数')}"></el-table-column>
  44. <el-table-column label="{:__('执行间隔')}">
  45. <template #default="{row}">
  46. {{parseTime(row.delay) || '立即执行'}}
  47. </template>
  48. </el-table-column>
  49. <el-table-column label="{:__('规则限制')}" width="200">
  50. <template #default="{row}">
  51. {{parseFilter(row.filter)}}
  52. </template>
  53. </el-table-column>
  54. <el-table-column label="{:__('上次执行时间')}" width="200">
  55. <template #default="{row}">
  56. {{parseLasttime(row.lasttime)}}
  57. </template>
  58. </el-table-column>
  59. <el-table-column label="{:__('错误')}" width="200">
  60. <template #default="{row}">
  61. <el-tag type="danger" v-if="row.error">{{row.error}}</el-tag>
  62. </template>
  63. </el-table-column>
  64. <el-table-column label="{:__('状态')}" width="120">
  65. <template #default="{row}">
  66. <el-switch active-value="normal" inactive-value="hidden" v-model="row.status"></el-switch>
  67. </template>
  68. </el-table-column>
  69. <el-table-column label="{:__('操作')}" width="120">
  70. <template #default="{row}">
  71. <el-button type="danger" size="small" @click="delEvent(row.id)">{:__('删除')}</el-button>
  72. </template>
  73. </el-table-column>
  74. </el-table>
  75. </el-form-item>
  76. <el-form-item label="{:__('运行日志')}:">
  77. <el-input type="textarea" autosize v-model="log.content" style="margin-bottom: 10px;"></el-input>
  78. <el-pagination :current-page="log.currentPage" :small="true" background @current-change="getLog" layout="prev, pager, next" :page-count="log.total" />
  79. </el-form-item>
  80. </el-form>
  81. </el-card>
  82. </template>
  83. <script>
  84. let inter;
  85. export default{
  86. data:{
  87. eventList:[],
  88. log:{
  89. currentPage:1,
  90. content:'',
  91. total:1
  92. },
  93. status:'',
  94. keeptime:0,
  95. stoptime:''
  96. },
  97. onLoad:function(){
  98. Yunqi.ajax.get('develop/queueLog',{type:'total'}).then(res=>{
  99. this.log.total=res;
  100. this.log.currentPage=res;
  101. });
  102. Yunqi.ajax.get('develop/queue').then(res=>{
  103. this.eventList=res;
  104. });
  105. this.getStatus();
  106. },
  107. methods: {
  108. changeStatus:function (status){
  109. Yunqi.ajax.post('develop/queueStatus',{status:status}).then(res=>{
  110. this.getStatus();
  111. if(status){
  112. this.log.total=1;
  113. this.log.currentPage=1;
  114. }
  115. }).catch(err=>{
  116. this.getStatus();
  117. });
  118. },
  119. getLog:function (e){
  120. this.log.currentPage=e;
  121. Yunqi.ajax.get('develop/queueLog',{type:'content',page:e}).then(res=>{
  122. this.log.content=res;
  123. });
  124. },
  125. getStatus:function (){
  126. if(inter){
  127. clearInterval(inter);
  128. }
  129. Yunqi.ajax.get('develop/queueStatus').then(res=>{
  130. this.status=res.status;
  131. this.keeptime=res.keeptime;
  132. this.stoptime=res.stoptime;
  133. inter=setInterval(()=>{
  134. if(this.keeptime%5===0 && this.log.currentPage==this.log.total){
  135. this.getLog(this.log.total);
  136. }
  137. this.keeptime++;
  138. },1000)
  139. });
  140. },
  141. delEvent:function (id){
  142. Yunqi.ajax.post('develop/delQueue',{id:id}).then(res=>{
  143. this.eventList=res;
  144. });
  145. },
  146. addEvent:function (){
  147. let that=this;
  148. Yunqi.api.open({
  149. url:'develop/addQueue',
  150. title:'添加任务',
  151. close:function (){
  152. Yunqi.ajax.get('develop/queue').then(res=>{
  153. that.eventList=res;
  154. });
  155. }
  156. });
  157. },
  158. parseTime:function (second){
  159. if(second===0){
  160. return 0;
  161. }
  162. if(second>0 && second<60){
  163. return second+'秒';
  164. }
  165. if(second>=60 && second<3600){
  166. let r=Math.floor(second/60)+'分钟';
  167. if(second%60>0){
  168. r+=second%60+'秒';
  169. }
  170. return r;
  171. }
  172. if(second>=3600 && second<86400){
  173. let r=Math.floor(second/3600)+'小时';
  174. if(second%3600>60){
  175. r+=Math.floor(second%3600/60)+'分钟';
  176. }
  177. if(second%3600%60>0){
  178. r+=second%3600%60+'秒';
  179. }
  180. return r;
  181. }
  182. if(second>=86400){
  183. let r=Math.floor(second/86400)+'天';
  184. if(second%86400>3600){
  185. r+=Math.floor(second%86400/3600)+'小时';
  186. }
  187. if(second%86400%3600>60){
  188. r+=Math.floor(second%86400%3600/60)+'分钟';
  189. }
  190. if(second%86400%3600%60>0){
  191. r+=second%86400%3600%60+'秒';
  192. }
  193. return r;
  194. }
  195. },
  196. parseFilter:function (obj){
  197. if(!obj){
  198. return '-';
  199. }
  200. let r='';
  201. if(obj.Y!==undefined){
  202. r+='year:'+obj.Y+' ';
  203. }
  204. if(obj.m!==undefined){
  205. r+='month:'+obj.m+' ';
  206. }
  207. if(obj.d!==undefined){
  208. r+='day:'+obj.d+' ';
  209. }
  210. if(obj.H!==undefined){
  211. r+='hours:'+obj.H+' ';
  212. }
  213. if(obj.i!==undefined){
  214. r+='minute:'+obj.i+' ';
  215. }
  216. if(obj.s!==undefined){
  217. r+='second:'+obj.s+' ';
  218. }
  219. //去掉r最后的空格
  220. return r.replace(/\s*$/,'');
  221. },
  222. parseLasttime:function (data){
  223. if(!data){
  224. return '-';
  225. }
  226. return data;
  227. }
  228. }
  229. }
  230. </script>
  231. <style>
  232. .status{
  233. display: flex;
  234. align-items: center;
  235. }
  236. </style>