Galactic/www/index.html

90 lines
26 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>UI</title>
<link rel="stylesheet" href="assets/css/sweetalert2.min.css">
<link rel="stylesheet" href="assets/css/iconfont.css">
<script type="text/javascript" src="assets/js/jquery.min.js"></script>
<script type="text/javascript" src="assets/js/vue.min.js"></script>
<script type="text/javascript" src="assets/js/axios.min.js"></script>
<script type="text/javascript" src="assets/js/lodash.min.js"></script>
<script type="text/javascript" src="assets/js/sweetalert2.min.js"></script>
<script type="text/javascript" src="assets/js/reconnecting-websocket.min.js"></script>
<style>body{user-select:none;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;background-color:#fff;font-family:Arial,sans-serif;background-color:#f4f4f4;margin:0;padding:0;display:flex;justify-content:center;align-items:center;height:100vh}[v-cloak]{display:none}h1{font-size:22px;color:#555;padding:0 2px}img{-webkit-user-drag:none;user-drag:none;-webkit-user-select:none;user-select:none}button{outline:0}.main{background-color:#fff;padding:0;margin:0;border-radius:0;box-shadow:0 0 10px rgba(0,0,0,.1);width:100%;max-width:480px;max-height:960px;text-align:center;align-items:center;overflow:auto;height:100vh}.head{position:sticky;top:0;margin:0;height:auto;z-index:500}.list{height:auto}.main::-webkit-scrollbar{width:4px}.main::-webkit-scrollbar-thumb{background-color:#ff6c6c;border-radius:0}.main::-webkit-scrollbar-track{background:#f3f3f3}.bar,.list{align-items:center}.bar{display:flex;justify-content:center}.logo{width:38px;height:38px;padding:2px}.user{color:#fff;padding:10px;margin:7px 5px;text-align:center;cursor:pointer;align-items:center;border-radius:5px;box-shadow:0 2px 4px rgba(0,0,0,.1);transition:all .15s}.plugin-all{color:#fff;padding:10px;margin:0 5px 0 5px;text-align:center;cursor:pointer;align-items:center;border-radius:0;box-shadow:0 2px 4px rgba(0,0,0,.1);transition:all .15s;border:1px solid #ccc;box-shadow:0 2px 5px rgba(80,80,80,.5);background:linear-gradient(rgba(0,0,0,.42),rgba(9,9,9,.38));backdrop-filter:blur(15px)}.user:hover{box-shadow:0 1px 8px rgba(96,96,96,.55)}.running{background-image:linear-gradient(45deg,#88e1c5,#9face6)}.running,.stopped{transition:all .15s}.stopped{background-image:linear-gradient(45deg,#b3b3b3,#e9ebec)}.plugins{background-image:linear-gradient(90deg,#fd9a9e,#fadacf);background-size:200% 200%;animation:gradientAnimation 3.5s ease infinite;transition:all .15s}@keyframes gradientAnimation{0%{background-position:0 50%}50%{background-position:100% 50%}to{background-position:0 50%}}.extend{display:block;position:relative;background-color:transparent}.extend-show-enter-active,.extend-show-leave-active{transition:opacity .12s}.extend-show-enter,.extend-show-leave-to{opacity:.05}.h_div{display:flex;justify-content:space-between;align-items:center;transition:background-color .3s}.v_div{display:flex;flex-direction:column;transition:background-color .3s}.label{display:flex;align-items:left;width:75%}.id,.name{display:inline-block;vertical-align:middle;font-family:Arial,sans-serif;margin:0;padding:0;height:auto;text-align:left;font-size:15px;font-weight:700;text-shadow:0 0 1px #ccc;overflow:hidden;white-space:nowrap}.id{width:auto;margin-right:auto}.name{margin:0 0 0 10px;cursor:pointer;max-width:240px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.logging,.result,.summary,.windows{display:inline-block;vertical-align:middle;font-family:Arial,sans-serif;height:auto;font-size:14px;font-weight:400;text-shadow:0 0 1px #ccc;white-space:nowrap;overflow:hidden;-webkit-marquee-style:slide;-webkit-marquee-speed:normal}.logging{font-weight:500;text-align:left;text-shadow:0 0 2px #ccc;width:222px;margin:0;padding:0;text-overflow:ellipsis}.result{margin:0 0 0 10px;font-weight:700;text-align:left;width:auto;max-width:250px;padding:0}.summary{text-align:left;width:180px;margin:0;padding:0;text-overflow:ellipsis}.windows{margin:0;text-align:right;width:65px}.h_divider{margin:4px 0;width:100%;height:1px}.h_divider,.v_divider{background-color:hsla(0,0%,100%,.35)}.v_divider{margin:0 4px;width:1px;height:24px}.close{font-family:inherit;font-size:1.5rem;font-weight:700;line-height:1;color:#000;text-shadow:0 0 0 #fff;position:relative;right:0;background-color:transparent;border:0;cursor:pointer;opacity:.38}.button{color:#fff;margin:2px 0;padding:10px 24px;font-size:16px;border:none;border-radius:999px;cursor:pointer}.button:disabled{pointer-events:none;filter:saturate(20%);opacity:.25}.die-plugin-shutdown-all-users{margin:0 1px;font-size:14px;background-color:rgba(255,0,0,.85);border:1px solid #aaa;border-radius:5px}.run{background-color:#4caf50}.die,.run{padding:6px 12px;font-size:14px;opacity:.95}.die{background-color:#e74c3c}.die-plugin-shutdown{background-color:#f09240}.button:hover{opacity:.8}.desc{display:inline-block;vertical-align:middle;font-family:Arial,sans-serif;margin:2px;padding:0;height:auto;text-align:center;font-size:16px;color:grey;font-weight:200;text-shadow:0 0 1px #ccc;max-width:360px;overflow:hidden;text-overflow:ellipsis;-webkit-marquee-style:slide;-webkit-marquee-speed:normal}.unselectable{user-select:none;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.rollbar{position:fixed;right:10px;bottom:10px;z-index:50;display:block;width:auto}.rollbar .rollbar-item{position:relative;margin-top:10px;width:40px;height:40px;background-color:#666;color:#fff;text-align:center;line-height:1.4;opacity:.5;cursor:pointer;transition:opacity .5s;-webkit-transition:all .3s ease-in-out;-moz-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.rollbar .rollbar-item:hover{color:#fff;opacity:.9}.iconfont{font-size:1rem}.iconfont,.iconfont-small{vertical-align:middle;font-style:normal;font-family:iconfont!important;-webkit-font-smoothing:antialiased;-webkit-text-stroke-width:.2px;-moz-osx-font-smoothing:grayscale}.iconfont-small{font-size:.875rem}.iconfont-big{font-size:1.1rem}.iconfont-big,.iconfont-x-big{vertical-align:middle;font-style:normal;font-family:iconfont!important;-webkit-font-smoothing:antialiased;-webkit-text-stroke-width:.2px;-moz-osx-font-smoothing:grayscale}.iconfont-x-big{font-size:1.875rem}.btn-group{text-align:left;margin:15px 0;display:flex;flex-wrap:wrap}.btn-group .text-item{vertical-align:middle;font-family:Arial,sans-serif;margin:0;padding:2px 4px;height:auto;font-size:13px;text-shadow:0 0 1px #ccc;width:88%}.btn-group .btn,.btn-group .text-item{display:inline;text-align:left;color:#fff;overflow:hidden;white-space:nowrap}.btn-group .btn{max-width:50%;margin:2px;background-color:rgba(0,0,0,.15);border:1px solid hsla(0,0%,100%,0);border-radius:4px;padding:12px;text-decoration:none;font-size:14px;cursor:pointer;text-overflow:ellipsis;flex:0 0 calc(50% - 4px);box-sizing:border-box}.btn-group .btn:hover{background-color:hsla(0,0%,100%,.05);border:1px solid hsla(0,0%,100%,.95)}.btn-group .btn:active{background-color:hsla(0,0%,100%,.15);border:1px solid hsla(0,0%,100%,.95)}@media (max-width:540px){.main{width:100%;height:99vh}}</style></head>
<body>
<div class="main" id="app" v-cloak>
<div class="bar" v-show="userOnlineCount == 0">
<img class="logo" src="assets/images/logo-chrome.png">
<h1 class="unselectable">用户管理</h1>
</div>
<div class="head" v-show="userOnlineCount">
<div class="plugin-all">
<div class="v_div">
<div class="h_div">
<p class="unselectable id">{{ pluginBatchExecutionStatus ? '正在执行:' + pluginBatchExecutionName : '批量执行' }}</p>
</div>
<div class="h_divider"></div>
<div v-show="!pluginBatchExecutionStatus" class="btn-group">
<button v-for="(plugin_id, plugin_index) in Object.keys(pluginList).sort()" :key="plugin_index" class="btn" @click.stop="pluginAllUsersRun(plugin_id, pluginList[plugin_id].requirements, $event)"><i class="iconfont top-flashlight_fill"></i><p class="text-item">{{ pluginList[plugin_id].name }}</p></button>
</div>
<button v-show="pluginBatchExecutionStatus" class="button unselectable die-plugin-shutdown-all-users" @click.stop="pluginAllUsersShutdown($event)">结束运行</button>
</div>
</div>
</div>
<div class="list" id="userList">
<div v-for="(item, key) in userDetails" :key="key">
<div :class="{'user': true, 'running': item.is_running && !item.plugin_running, 'stopped': !item.is_running && !item.plugin_running, 'plugins': item.plugin_running}" @mouseleave="closedTab(item.user_id)">
<div class="v_div">
<div class="h_div" @dblclick.stop="doubleTab(item.user_id, $event)">
<div class="label">
<p class="unselectable id" :title="item.user_id" @click.stop="userSetName(item.user_id, $event)" v-if="!item.user_name || item.user_name.trim() === ''">未命名</p>
<p class="unselectable id" :title="item.user_id" @click.stop="userSetName(item.user_id, $event)" v-else>{{ item.user_name }}</p>
<p class="unselectable result" :title="item.plugin_execution_result" :style="{ color: item.plugin_execution_result_color }">{{ item.plugin_execution_result }}</p>
</div>
<a class="close" @click.stop="userDel(item.user_id, $event)"><span class="unselectable" aria-hidden="true">×</span></a>
</div>
<div class="h_divider"></div>
<div class="h_div" @click.stop="toggleTab(item.user_id, $event)">
<div class="v_div">
<div class="h_div" v-if="item.is_running && userLoggingList[item.user_id] && (parseInt(Date.now() / 1000) - userLoggingList[item.user_id].time) < 10">
<p class="unselectable logging" :title="userLoggingList[item.user_id].data">{{ userLoggingList[item.user_id].data }}</p>
</div>
<div class="h_div" v-else>
<p class="unselectable summary" v-if="item.is_running !== true">用户未运行</p>
<p class="unselectable summary" v-else>{{ item.alert || item.title }}</p>
<p class="unselectable windows" v-if="item.is_running !== true"></p>
<p class="unselectable windows" v-else>{{ !item.window_handles ? '0个页面' : item.window_handles.length + '个页面' }}</p>
</div>
</div>
<div class="v_divider"></div>
<div class="unselectable">
<button class="button unselectable run" :disabled="item.is_running == 1" @click.stop="userRun(item.user_id, $event)">运行</button>
<button v-if="!item.plugin_running" class="button unselectable die" :disabled="item.is_running == 0" @click.stop="userDie(item.user_id, $event)">停止</button>
<button v-else class="button unselectable die die-plugin-shutdown" :disabled="item.is_running == 0" @click.stop="pluginShutdown(item.user_id, $event)">停止</button>
</div>
</div>
</div>
<transition name="extend-show">
<div class="extend" v-show="userPluginDisplayStatus[item.user_id] && item.is_running && !item.plugin_running">
<div class="btn-group">
<button v-for="(plugin_id, plugin_index) in Object.keys(pluginList).sort()" :key="plugin_index" class="btn" @click.stop="pluginRun(item.user_id, plugin_id, pluginList[plugin_id].requirements, $event)"><i class="iconfont top-flashlight_fill"></i><p class="text-item">{{ pluginList[plugin_id].name }}</p></button>
</div>
</div>
</transition>
</div>
</div>
<p class="desc unselectable" v-if="Object.keys(userDetails).length === 0">暂时还没有用户,请先添加~</p>
<button class="button unselectable" id="addUser" @click.stop="userAdd($event)"></button>
</div>
</div>
<div class="rollbar"><div class="rollbar-item" id="back-to-top" style="height:0" title="返回顶部"><i class="iconfont-x-big top-top"></i></div></div>
<script>window.onload=function(){window.addEventListener('mousewheel',function(event){if(event.ctrlKey===true||event.metaKey){event.preventDefault()}},{passive:false});document.addEventListener('keydown',function(event){if((event.ctrlKey===true||event.metaKey===true)&&(event.which===61||event.which===107||event.which===173||event.which===109||event.which===187||event.which===189)){event.preventDefault()}},false)}</script>
<script>window.addEventListener("load",function(){let backBtn=document.getElementById("back-to-top");let bodyObj=document.getElementById("app");let hiddenControl=function(element,isHidden){if(isHidden){backBtn.style.height="0"}else{backBtn.style.height="40px"}};bodyObj.addEventListener("scroll",function(){if(bodyObj.scrollTop>bodyObj.offsetHeight||bodyObj.scrollTop>300){hiddenControl(backBtn,0)}else{hiddenControl(backBtn,1)}});backBtn.addEventListener("click",function(e){e.preventDefault();bodyObj.scrollTo({top:0,behavior:"smooth"})})});</script>
<script>const Toast=Swal.mixin({toast:true,position:"center",showConfirmButton:false,timer:2250,timerProgressBar:false,});const Backs=Swal.mixin({html:"",timer:750,timerProgressBar:true,showConfirmButton:false,allowOutsideClick:false,});const Message=Swal.mixin({toast:true,position:"top",width:"480px",background:"#727272",color:"#fdfdfd",showConfirmButton:false,timer:3500,timerProgressBar:false,icon:"info",iconColor:"#d5d5d5",didOpen:(toast)=>{toast.onmouseenter=Swal.stopTimer;toast.onmouseleave=Swal.resumeTimer},});const FilePreferred=Swal.mixin({text:"选择文件来源",input:"select",inputOptions:{"preferred":"首选文件","upload":"上传文件"},showConfirmButton:true,showCancelButton:true,confirmButtonText:"确定",cancelButtonText:"取消",allowOutsideClick:false,});const FileUpload=Swal.mixin({text:"打开文件",input:"file",inputAttributes:{accept:"*"},inputValidator:(value)=>{if(value===null){return"还未选择文件"}},showConfirmButton:true,showCancelButton:true,confirmButtonText:"确定",cancelButtonText:"取消",allowOutsideClick:false,showLoaderOnConfirm:true,preConfirm:(files)=>{if(!(files instanceof FileList)){files=[files]}let formData=new FormData();for(let i=0;i<files.length;i++){formData.append("files",files[i])}return axios.post("./upload_files",formData).then((response)=>{if(response.data.code!=0){throw new Error(response.data.info);}return response.data.data[0]}).catch((error)=>{Swal.showValidationMessage(error);return false})},});const MultFileUpload=Swal.mixin({text:"打开文件",input:"file",inputAttributes:{multiple:"multiple",accept:"*"},inputValidator:(value)=>{if(value===null){return"还未选择文件"}},showConfirmButton:true,showCancelButton:true,confirmButtonText:"确定",cancelButtonText:"取消",allowOutsideClick:false,showLoaderOnConfirm:true,preConfirm:(files)=>{if(!(files instanceof FileList)){files=[files]}let formData=new FormData();for(let i=0;i<files.length;i++){formData.append("files",files[i])}return axios.post("./upload_files",formData).then((response)=>{if(response.data.code!=0){throw new Error(response.data.info);}return response.data.data}).catch((error)=>{Swal.showValidationMessage(error);return false})},});const TextUpload=Swal.mixin({text:"输入内容",input:"text",showConfirmButton:true,showCancelButton:true,confirmButtonText:"确定",cancelButtonText:"取消",allowOutsideClick:false,});const MultTextUpload=Swal.mixin({text:"输入内容",input:"textarea",showConfirmButton:true,showCancelButton:true,confirmButtonText:"确定",cancelButtonText:"取消",allowOutsideClick:false,});const MixinInput=async function(requirements,preferred_file){if(Array.isArray(requirements)){let inputClassList={"file-preferred":FilePreferred,"file":FileUpload,"file-mult":MultFileUpload,"text":TextUpload,"text-mult":MultTextUpload,};let _reqs=requirements;let _lens=requirements.length;let _results=[];for(let i=0;i<_lens;i++){let inputClass=inputClassList[_reqs[i]["type"]];if(!inputClass){Toast.fire({icon:"error",title:"不支持的输入类型"});return null}let result=null;if(inputClass===inputClassList["file"]&&preferred_file){result=await inputClassList["file-preferred"].fire({text:_reqs[i]["html"],inputOptions:{"preferred":"首选文件","upload":"上传文件"}});if(!result.isConfirmed){return null}else{if(result.value=="preferred"){_results.push(preferred_file);continue}}}result=await inputClass.fire({text:_reqs[i]["html"]});if(!result.isConfirmed){return null}else{_results.push(result.value)}}return _results}else{return[]}};new Vue({el:"#app",data:{userOnlineCount:null,userDetails:{},pluginBatchExecutionId:null,pluginBatchExecutionName:null,pluginBatchExecutionTime:null,pluginBatchExecutionStatus:null,pluginBatchExecutionResult:null,pluginList:{},pluginPreferredFile:null,userLoggingList:{},userPluginDisplayStatus:{},messageSocket:null,isConnected:true,},created(){this.fetchPluginPreferredFile();this.fetchPluginData();this.fetchData();this.initMessageSocket();setInterval(this.fetchPluginPreferredFile,2250);setInterval(this.fetchData,1750)},methods:{fetchPluginPreferredFile:_.throttle(function(){axios.get("./plugin_preferred_file").then((response)=>{let newData=response.data;this.pluginPreferredFile=response.data["data"]}).catch((error)=>{})},1000),fetchPluginData:_.throttle(function(){axios.get("./plugin_list").then((response)=>{let newData=response.data;for(let pluginId in this.pluginList){if(!newData[pluginId]){Vue.delete(this.pluginList,pluginId)}}for(let pluginId in newData){Vue.set(this.pluginList,pluginId,newData[pluginId])}}).catch((error)=>{})},1000),fetchData:_.throttle(function(){axios.get("./user_all_details").then((response)=>{let userOnlineCount=response.data['user_online_count'];let userDetails=response.data['user_details'];let pluginBatchExecutionId=response.data['plugin_batch_execution_id'];let pluginBatchExecutionName=response.data['plugin_batch_execution_name'];let pluginBatchExecutionTime=response.data['plugin_batch_execution_time'];let pluginBatchExecutionStatus=response.data['plugin_batch_execution_status'];let pluginBatchExecutionResult=response.data['plugin_batch_execution_result'];this.userOnlineCount=userOnlineCount;this.pluginBatchExecutionId=pluginBatchExecutionId;this.pluginBatchExecutionName=pluginBatchExecutionName;this.pluginBatchExecutionTime=pluginBatchExecutionTime;this.pluginBatchExecutionStatus=pluginBatchExecutionStatus;this.pluginBatchExecutionResult=pluginBatchExecutionResult;for(let userId in this.userDetails){if(!userDetails[userId]){Vue.delete(this.userDetails,userId)}}for(let userId in userDetails){Vue.set(this.userDetails,userId,userDetails[userId])}}).catch((error)=>{});axios.get("./200").then((response)=>{this.isConnected=true}).catch((error)=>{if(this.isConnected){Swal.fire({title:"连接错误",text:"请检查后端服务是否已运行",icon:"error",confirmButtonText:"确定",allowOutsideClick:false,})}this.isConnected=false})},1000),initMessageSocket:function(){this.messageSocket=new ReconnectingWebSocket((window.location.protocol==="https:"?"wss://":"ws://")+window.location.host+"/instant_message",);this.messageSocket.onopen=function(event){console.log("MessageSocket Connection Established.")};this.messageSocket.onmessage=(event)=>{if(event.data.startsWith("Hello")){return null}try{let message=JSON.parse(event.data);switch(message.type){case"logging":Vue.set(this.userLoggingList,message.data.user_id,{time:message.time,data:message.data.content,});break;case"message":Message.fire({title:message.data.title,text:message.data.content,});break}}catch(error){}};this.messageSocket.onerror=function(event){console.error("Error:",event)};this.messageSocket.onclose=function(event){console.log("MessageSocket Connection Closed.")}},toggleTab(user_id,event){event.stopPropagation();this.$set(this.userPluginDisplayStatus,user_id,!this.userPluginDisplayStatus[user_id],)},doubleTab(user_id,event){event.stopPropagation();if(this.userDetails[user_id].is_running){this.userFocusWindow(user_id,event)}else{this.userRun(user_id,event)}},closedTab(user_id){this.$set(this.userPluginDisplayStatus,user_id,false)},userFocusWindow(user_id,event){event.stopPropagation();axios.post("./user_focus_window",{data:{user_id:user_id}},{headers:{"Content-Type":"application/json"}},).then((response)=>{let data=response.data;if(data.code!==0){Toast.fire({icon:"warning",title:data.info})}}).catch((error)=>{Swal.fire({title:"请求失败",text:error,icon:"error",confirmButtonText:"确定",allowOutsideClick:false,})})},pluginRun(user_id,plugin_id,requirements,event){event.stopPropagation();Backs.fire({html:"正在加载...",timer:250});MixinInput(requirements,this.pluginPreferredFile).then((result)=>{if(result===null){return null}axios.post("./plugin_run",{data:{user_id:user_id,plugin_id:plugin_id,requirements:result,},},{headers:{"Content-Type":"application/json"}},).then((response)=>{let data=response.data;if(data.code!==0){Toast.fire({icon:"warning",title:data.info})}}).catch((error)=>{Swal.fire({title:"请求失败",text:error,icon:"error",confirmButtonText:"确定",allowOutsideClick:false,})})})},pluginShutdown(user_id,event){event.stopPropagation();Backs.fire({html:"正在结束...",timer:250});axios.post("./plugin_shutdown",{data:{user_id:user_id}},{headers:{"Content-Type":"application/json"}},).then((response)=>{let data=response.data;if(data.code!==0){Toast.fire({icon:"warning",title:data.info})}}).catch((error)=>{Swal.fire({title:"请求失败",text:error,icon:"error",confirmButtonText:"确定",allowOutsideClick:false,})});this.fetchData()},pluginAllUsersRun(plugin_id,requirements,event){event.stopPropagation();Backs.fire({html:"正在加载...",timer:999});MixinInput(requirements,this.pluginPreferredFile).then((result)=>{if(result===null){return null}axios.post("./plugin_all_users_run",{data:{plugin_id:plugin_id,requirements:result,},},{headers:{"Content-Type":"application/json"}},).then((response)=>{let data=response.data;if(data.code!==0){Toast.fire({icon:"warning",title:data.info})}}).catch((error)=>{Swal.fire({title:"请求失败",text:error,icon:"error",confirmButtonText:"确定",allowOutsideClick:false,})})})},pluginAllUsersShutdown(event){event.stopPropagation();Backs.fire({html:"正在结束...",timer:250});axios.post("./plugin_all_users_shutdown",{data:null},{headers:{"Content-Type":"application/json"}},).then((response)=>{let data=response.data;if(data.code!==0){Toast.fire({icon:"warning",title:data.info})}}).catch((error)=>{Swal.fire({title:"请求失败",text:error,icon:"error",confirmButtonText:"确定",allowOutsideClick:false,})});this.fetchData()},userRun(user_id,event){event.stopPropagation();Backs.fire({html:"正在启动...",timer:1500});axios.post("./user_run",{data:{user_id:user_id}},{headers:{"Content-Type":"application/json"}},).then((response)=>{let data=response.data;if(data.code!==0){Toast.fire({icon:"warning",title:data.info})}}).catch((error)=>{Swal.fire({title:"请求失败",text:error,icon:"error",confirmButtonText:"确定",allowOutsideClick:false,})});this.fetchData()},userDie(user_id,event){event.stopPropagation();Backs.fire({html:"正在关闭...",timer:2500});axios.post("./user_die",{data:{user_id:user_id}},{headers:{"Content-Type":"application/json"}},).then((response)=>{let data=response.data;if(data.code!==0){Toast.fire({icon:"warning",title:data.info})}}).catch((error)=>{Swal.fire({title:"请求失败",text:error,icon:"error",confirmButtonText:"确定",allowOutsideClick:false,})});this.fetchData()},userAdd(event){event.stopPropagation();Backs.fire({html:"请稍候..."});axios.post("./user_add",{data:{user_id:"u"+String(new Date().getTime())}},{headers:{"Content-Type":"application/json"}},).then((response)=>{let data=response.data;if(data.code!==0){Toast.fire({icon:"warning",title:data.info})}}).catch((error)=>{Swal.fire({title:"请求失败",text:error,icon:"error",confirmButtonText:"确定",allowOutsideClick:false,})});this.fetchData()},userDel(user_id,event){event.stopPropagation();Swal.fire({title:"",text:"确认删除用户数据?",icon:"warning",showCancelButton:true,confirmButtonText:"确定",cancelButtonText:"取消",allowOutsideClick:false,}).then((result)=>{if(result.isConfirmed){Backs.fire({html:"请稍候..."});axios.post("./user_del",{data:{user_id:user_id}},{headers:{"Content-Type":"application/json"}},).then((response)=>{let data=response.data;if(data.code!==0){Toast.fire({icon:"warning",title:data.info})}}).catch((error)=>{Swal.fire({title:"请求失败",text:error,icon:"error",confirmButtonText:"确定",allowOutsideClick:false,})});this.fetchData()}})},userSetName(user_id,event){event.stopPropagation();Swal.fire({input:"text",inputLabel:"修改名称",showCancelButton:true,confirmButtonText:"确定",cancelButtonText:"取消",allowOutsideClick:false,inputValue:this.userDetails[user_id].user_name,inputValidator:(value)=>{if(value==""){return"名称不能为空"}if(value.includes("<")||value.includes(">")){return"含有非法字符"}if(value.length>12){return"长度超出限制"}},}).then((result)=>{if(result.isConfirmed){let inputValue=result.value;Backs.fire({html:"请稍候..."});axios.post("./user_set_name",{data:{user_id:user_id,user_name:inputValue.trim()}},{headers:{"Content-Type":"application/json"}},).then((response)=>{let data=response.data;if(data.code!==0){Toast.fire({icon:"warning",title:data.info})}}).catch((error)=>{Swal.fire({title:"请求失败",text:error,icon:"error",confirmButtonText:"确定",allowOutsideClick:false,})});this.fetchData()}})},},});</script>
</body>
</html>