├── .gitignore ├── .prettierrc ├── HostsSwitch.jpg ├── README.md ├── app.ico ├── default.aproj ├── dist └── HostsSwitch.exe ├── lib └── hosts.aardio ├── main.aardio ├── web ├── addition.75f59799.svg ├── download.779c3df5.svg ├── edit.e5e6ea37.svg ├── favicon.da3735d5.png ├── home.3a7af05d.svg ├── index.aardio ├── lock.623ff62a.svg ├── main.2a31e670.js ├── main.a46e3e18.css ├── record.56e10638.svg ├── recordFind.08a261bc.svg ├── refresh.0b748f9a.svg ├── save.8ed52c9e.svg ├── subtraction.600c820b.svg └── unlock.6ef52b3f.svg └── web_source ├── .gitignore ├── .prettierrc ├── package.json ├── src ├── asset │ ├── addition.svg │ ├── download.svg │ ├── edit.svg │ ├── favicon.png │ ├── flag.svg │ ├── home.svg │ ├── interpretation.svg │ ├── link.svg │ ├── lock.svg │ ├── menu.svg │ ├── record.svg │ ├── recordFind.svg │ ├── refresh.svg │ ├── save.svg │ ├── subtraction.svg │ └── unlock.svg ├── index.html ├── js │ ├── CodeMirror │ │ ├── hosts.css │ │ ├── index.ts │ │ └── modeHosts.js │ ├── bus.ts │ ├── contextMenu.ts │ ├── dataAction │ │ ├── DATA.d.ts │ │ ├── DATA.ts │ │ ├── defaultConfig.ts │ │ ├── index.ts │ │ └── render.ts │ ├── dialog.ts │ ├── init.ts │ ├── main.ts │ ├── textarea.ts │ ├── types │ │ └── aardio.d.ts │ └── util.ts ├── lib │ └── template.js └── styles │ ├── base.less │ ├── index.less │ └── ui.less └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | .build -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 200, 3 | "tabWidth": 2, 4 | "semi": true, 5 | "useTabs": false, 6 | "singleQuote": true, 7 | "bracketSpacing": true 8 | } -------------------------------------------------------------------------------- /HostsSwitch.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lnncoco/hosts-switch/bc6dfc271831091629d6bc30f4e2b651a6409157/HostsSwitch.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HostsSwitch 2 | 3 | ![HostsSwitch](./HostsSwitch.jpg) 4 | 5 | ## 介绍 6 | 7 | 这是一个为了练手做的小工具。看见`aardio`官方有一个修改版的[`hostsSwitchHelper`](https://github.com/aardio/hostsSwitchHelper),于是学习了一下实现。 8 | 自己重头设计实现了界面和逻辑,逻辑都在前端,只有涉及保存文件之类放到`aardio`里。 9 | 前端使用`LuLu UI`+`LESS`+`TypeScript`实现。 10 | 11 | 功能与`SwitchHosts!`类似,就是方便修改系统 Hosts 信息的小工具。与之不同的是,每个项都是一份独立的 Host 信息,可以自己手动输入,也可以设置`url`参数,方便网络`Hosts`更新(默认会走系统代理设置)。侧边`Switch开关`开启时会自动将所有开启的数据合并,然后存入系统的`Hosts`文件中。 12 | 13 | ### 目录 14 | 15 | `dist`:存放一份编译后的`exe`应用程序 16 | `lib`:`aardio`的用户库文件存放目录 17 | `web`:前端编译后的文件,`aardio`打包使用的文件 18 | `web_source`:前端项目源码。使用`parcel`工具 19 | 20 | ### 修改生成 21 | 22 | - 在`web_source`目录中执行 `npm i` 安装依赖 23 | - 安装完成后,执行 `npm run dev` 启动项目,然后在`aardio`中同时启动,此时`aardio`的页面会访问本地的前端项目,可以实时修改查看(不知道是`aardio`不兼容`parcel`还是本来就是如此,在浏览器直接访问`aardio`的依赖会报错导致无法正常显示程序)。要确保 `6060` 端口未被占用,否则需要修改响应代码 24 | - 修改完成后使用 `npm run build` 编译,程序会自动生成到父级的`web`目录下 25 | -------------------------------------------------------------------------------- /app.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lnncoco/hosts-switch/bc6dfc271831091629d6bc30f4e2b651a6409157/app.ico -------------------------------------------------------------------------------- /default.aproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /dist/HostsSwitch.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lnncoco/hosts-switch/bc6dfc271831091629d6bc30f4e2b651a6409157/dist/HostsSwitch.exe -------------------------------------------------------------------------------- /lib/hosts.aardio: -------------------------------------------------------------------------------- 1 | namespace hosts; 2 | 3 | import fsys; 4 | import fsys.hosts; 5 | import fsys.table; 6 | import inet.http; 7 | 8 | 9 | fsys.hosts.ownCacls(); // hosts夺权,修正一些系统hosts无法编辑 10 | 11 | path = "~/"; 12 | backupFileName = 'system.bak'; 13 | 14 | // 配置文件 15 | config = fsys.table("~/config.hosts"); 16 | config.load(); 17 | 18 | // 获取完整保存文件路径 19 | getSavePath = function(name){ 20 | if(!name) return null,false,'请输入文件名'; 21 | var pathDir = ..io.fullpath(path); 22 | return pathDir ++ name,true,""; 23 | } 24 | 25 | // 判断文件是否存在 26 | isExistFile = function(name){ 27 | return !!..io.exist(path++name); 28 | } 29 | 30 | /** 31 | * 获取系统Hosts 32 | **/ 33 | getSystemHosts = function(){ 34 | return fsys.hosts.loadText(); 35 | } 36 | 37 | /** 38 | * 保存到系统Hosts 39 | * @param {string} content 40 | **/ 41 | saveSystemHosts = function(content){ 42 | return ..fsys.hosts.saveText(content); 43 | } 44 | 45 | /** 46 | * 刷新DNS缓存 47 | **/ 48 | clearDnsCache = function(){ 49 | fsys.hosts.flushDns(); 50 | return true; 51 | } 52 | 53 | /** 54 | * 发送请求获取网络Hosts 55 | * @param {string} url 56 | * @param {Object} proxy 57 | **/ 58 | requestHosts = function(url, proxy){ 59 | if(!proxy) proxy = {} 60 | var http = inet.http(proxy.ua, proxy.host); 61 | if(proxy.user && proxy.password) http.setProxyAuth(proxy.user, proxy.password); 62 | var html,err,errCode = http.get(url); 63 | if(html) return { code = 0, message = 'success', html = html } 64 | else { 65 | if(http.statusCode) return { code = http.statusCode, message = http.lastResponse() } 66 | else return { code = errCode || 9, message = err } 67 | } 68 | } 69 | 70 | /** 71 | * 备份系统文件 72 | * @param {boolean} coverage 是否强制覆盖 73 | **/ 74 | backupLocalHosts = function(coverage = false){ 75 | var path,status,errMsg = getSavePath(backupFileName) 76 | if(!status) return status 77 | if(isExistFile(backupFileName) && !coverage) return status; 78 | return ..string.save(path, getSystemHosts()); 79 | } 80 | 81 | /** 82 | * 获取所有数据 83 | * @param {table} data 所有数据 84 | **/ 85 | getConfigData = function(){ 86 | return config; 87 | } 88 | 89 | /** 90 | * 保存所有数据 91 | * @param {table} data 所有数据 92 | **/ 93 | saveConfigData = function(data){ 94 | config.main = data; 95 | config.time = ..time.now(); 96 | return config.save(); 97 | } 98 | 99 | 100 | /**intellisense(hosts) 101 | clearDnsCache() = 刷新DNS缓存 102 | requestHosts() = 从url获取Hosts信息 103 | getSystemHosts() = 获取系统的Hosts信息 104 | saveSystemHosts() = 保存到系统的Hosts 105 | backupLocalHosts() = 备份系统文件 106 | getConfigData() = 获取所有数据 107 | saveConfigData() = 保存所有数据 108 | end intellisense**/ 109 | -------------------------------------------------------------------------------- /main.aardio: -------------------------------------------------------------------------------- 1 | import fsys.hosts; 2 | import chrome.app; 3 | import hosts; 4 | 5 | var theApp = chrome.app(); 6 | 7 | /* 8 | external定义的对象可以通过aardio进行调用 9 | */ 10 | theApp.external = { 11 | 12 | //获取本地hosts 13 | getSystemHosts = hosts.getSystemHosts; 14 | 15 | //获取本地hosts 16 | saveSystemHosts = hosts.saveSystemHosts; 17 | 18 | //手动刷新dns缓存 19 | clearDnsCache = hosts.clearDnsCache; 20 | 21 | // 发送请求获取网络HOSTS 22 | requestHosts = hosts.requestHosts; 23 | 24 | // 备份系统文件 25 | backupLocalHosts = hosts.backupLocalHosts; 26 | 27 | // 获取配置信息 28 | getConfigData = hosts.getConfigData; 29 | 30 | // 保存配置信息 31 | saveConfigData = hosts.saveConfigData; 32 | 33 | } 34 | 35 | /* 36 | // 加载一个页面完成会触发这个事件(要求引用了"/aardio.js") 37 | theApp.onUrlReady = function($,url){ 38 | 39 | } 40 | 41 | // 窗口关闭时触发 42 | theApp.onQuit = function($,url){ 43 | 44 | } 45 | */ 46 | 47 | //WebSocke/RPC中遇到的错误都会触发这个函数,可以在这里自定义错误处理方式 48 | theApp.ws.onError = function(hSocket,err){ 49 | errput(err, "chrome/rpc error");//当然也可以在 global.onError 里自定义全部的错误信息怎么显示 50 | } 51 | 52 | var url = "/web/index.aardio" 53 | 54 | // 调试模式 55 | if(_STUDIO_INVOKED){ 56 | import web.rest.client; 57 | if( web.rest.client().api("http://localhost:6060/",,"HostsSwitch").get() ){ 58 | url = "http://localhost:6060/"; 59 | } 60 | } 61 | 62 | // 窗口大小 63 | theApp.indexReady( 64 | function(){ 65 | //theApp.setPos(,,820,430) 66 | } 67 | ) 68 | 69 | // 正式的启动chrome进程,aardio会自动把下面的文件转换为服务端请求 70 | theApp.start(url); 71 | 72 | // 网页中可以调用 aardio.quit() 退出,也可以直接关闭chrome窗口退出 73 | win.loopMessage(); 74 | -------------------------------------------------------------------------------- /web/addition.75f59799.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/download.779c3df5.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/edit.e5e6ea37.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/favicon.da3735d5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lnncoco/hosts-switch/bc6dfc271831091629d6bc30f4e2b651a6409157/web/favicon.da3735d5.png -------------------------------------------------------------------------------- /web/home.3a7af05d.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/index.aardio: -------------------------------------------------------------------------------- 1 | HostsSwitch
修改配置
标签名称:
远程地址:
-------------------------------------------------------------------------------- /web/lock.623ff62a.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/main.a46e3e18.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}[hidden],template{display:none}@charset "UTF-8";.ui-button{display:inline-block;line-height:20px;font-size:14px;text-align:center;color:#4c5161;border-radius:4px;border:1px solid #d0d0d5;padding:9px 15px;min-width:80px;background-color:#fff;background-repeat:no-repeat;background-position:50%;text-decoration:none;box-sizing:border-box;transition:border-color .15s,box-shadow .15s,opacity .15s;font-family:inherit;cursor:pointer;overflow:visible}.ui-button[width="100%"]{width:100%}div.ui-button{display:block}[type=submit]:not([class]){position:absolute;clip:rect(0 0 0 0)}@supports (-webkit-mask:none){[tabindex],[type=button],[type=submit],button{outline:0 none}}::-moz-focus-inner{border:0}button.ui-button,input.ui-button{height:40px}.ui-button:hover{color:#4c5161;text-decoration:none}.ui-button:not(.disabled):not(.loading):not(:disabled):hover{border-color:#ababaf;box-shadow:inset 0 1px 2px rgba(0,0,0,.01),inset 0 0 0 100px rgba(0,0,0,.05)}.ui-button:not(.disabled):not(.loading):not(:disabled):active{box-shadow:inset 0 1px 2px rgba(0,0,0,.1),inset 0 0 0 100px rgba(0,0,0,.1)}.ui-button[data-type=danger],.ui-button[data-type=error],.ui-button[data-type=primary],.ui-button[data-type=remind],.ui-button[data-type=success],.ui-button[data-type=warn],.ui-button[data-type=warning]{border:0;padding-top:10px;padding-bottom:10px;color:#fff}.ui-button[data-type=primary],.ui-button[data-type=remind]{background-color:#2a80eb}.ui-button[data-type=success]{background-color:#1cad70}.ui-button[data-type=warn],.ui-button[data-type=warning]{background-color:#f59b00}.ui-button[data-type=danger],.ui-button[data-type=error]{background-color:#eb4646}.ui-button.disabled,.ui-button:disabled{opacity:.4;cursor:default}.ui-button.loading{color:transparent!important;background-position:50%;background-repeat:no-repeat;position:relative;cursor:default}.ui-button.loading:before,input.ui-button.loading{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M0 512a512 512 0 101024 0A512 512 0 100 512z' fill='%232a80eb'/%3E%3C/svg%3E"),url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M0 512a512 512 0 101024 0A512 512 0 100 512z' fill='%232a80eb'/%3E%3C/svg%3E"),url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M0 512a512 512 0 101024 0A512 512 0 100 512z' fill='%232a80eb'/%3E%3C/svg%3E");background-position-x:calc(50% - 10px),50%,calc(50% + 10px);background-position-y:18px,18px,18px;background-size:5px 5px;animation:bubbling 1s infinite}.ui-button[data-type]:not([data-type=normal]).loading:before,input.ui-button[data-type]:not([data-type=normal]).loading{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M0 512a512 512 0 101024 0A512 512 0 100 512z' fill='%23fff'/%3E%3C/svg%3E"),url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M0 512a512 512 0 101024 0A512 512 0 100 512z' fill='%23fff'/%3E%3C/svg%3E"),url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M0 512a512 512 0 101024 0A512 512 0 100 512z' fill='%23fff'/%3E%3C/svg%3E")}.ui-button.loading:before{content:"";position:absolute;left:0;top:0;right:0;bottom:0;background-repeat:no-repeat}.ui-button.loading:before,div:invalid{width:20px;height:20px;background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M512 1024q-104 0-199-40-92-39-163-110T40 711Q0 616 0 512q0-15 10.5-25.5T36 476t25.5 10.5T72 512q0 90 35 171 33 79 94 140t140 95q81 34 171 34t171-35q79-33 140-94t95-140q34-81 34-171t-35-171q-33-79-94-140t-140-95q-81-34-171-34-15 0-25.5-10.5T476 36t10.5-25.5T512 0q104 0 199 40 92 39 163 110t110 163q40 95 40 199t-40 199q-39 92-110 163T711 984q-95 40-199 40z' fill='%232a80eb'/%3E%3C/svg%3E") no-repeat 50%;background-size:20px 20px;margin:auto;animation:spin 1s linear infinite}.ui-button[data-type]:not([data-type=normal]).loading:before,div:invalid{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M512 1024q-104 0-199-40-92-39-163-110T40 711Q0 616 0 512q0-15 10.5-25.5T36 476t25.5 10.5T72 512q0 90 35 171 33 79 94 140t140 95q81 34 171 34t171-35q79-33 140-94t95-140q34-81 34-171t-35-171q-33-79-94-140t-140-95q-81-34-171-34-15 0-25.5-10.5T476 36t10.5-25.5T512 0q104 0 199 40 92 39 163 110t110 163q40 95 40 199t-40 199q-39 92-110 163T711 984q-95 40-199 40z' fill='%23fff'/%3E%3C/svg%3E")}@keyframes bubbling{0%{background-position-y:18px,18px,18px}15%{background-position-y:15px,18px,18px}30%{background-position-y:17px,15px,18px}45%{background-position-y:18px,17px,15px}60%{background-position-y:18px,18px,17px}}.ui-button.error{border-color:#eb4646!important}input[type=checkbox]:not(.ui-visible){position:absolute;opacity:0;width:20px;height:20px;cursor:pointer;z-index:-1}.ui-visible+.ui-checkbox{display:none}.ui-checkbox{display:inline-block;width:20px;height:20px;border:1px solid transparent;border-radius:4px;box-sizing:border-box;box-shadow:inset 0 1px,inset 1px 0,inset -1px 0,inset 0 -1px;background-color:#fff;background-clip:content-box;color:#d0d0d5;transition:color .2s,background-color .1s;-webkit-user-select:none;-ms-user-select:none;user-select:none;vertical-align:-5px;overflow:hidden}.ui-checkbox+label{margin-left:5px}:disabled+.ui-checkbox,:not(:disabled)+.ui-checkbox:hover{color:#ababaf}:focus+.ui-checkbox{color:#2a80eb}:focus+.ui-checkbox:hover{color:#0057c3}:checked+.ui-checkbox{color:#2a80eb;background-color:#2a80eb}:checked+.ui-checkbox:hover,:checked:focus+.ui-checkbox{color:#0057c3;background-color:#0057c3}.ui-checkbox:after{content:"";display:block;width:100%;height:100%;background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M920.185 224.838c-33.782-33.935-88.619-33.935-122.464 0L409.955 614.564 226.231 429.952c-33.782-33.935-88.68-33.935-122.461 0-33.784 33.997-33.784 89.108 0 123.044l244.925 246.118c33.782 33.998 88.68 33.998 122.463 0l449.028-451.201c33.843-33.967 33.843-89.048-.001-123.075z' fill='%23fff'/%3E%3C/svg%3E") no-repeat 50%;background-size:12px 12px;visibility:hidden}:checked+.ui-checkbox:after{visibility:visible}:disabled+.ui-checkbox{opacity:.38}.error.ui-checkbox{color:#eb4646}input[type=color]{opacity:0}.ui-color-input{width:40px;height:40px;margin:0;padding:0;border:0;opacity:0;vertical-align:middle;text-indent:-999px;position:relative;z-index:-1}.ui-color-track{display:inline;position:absolute;width:40px;height:40px;border-radius:4px;background-color:rgba(25,28,34,.2);cursor:pointer}.ui-color-thumb{display:block;margin:7px auto;width:24px;height:24px;border:1px solid #f7f9fa;border-radius:3px;background-color:#4c5161;background-clip:content-box;transition:background-color .25s}.ui-color-container{display:none;position:absolute;width:241px;padding:10px 12px;border-radius:4px;background-color:#f7f9fa;box-shadow:0 2px 5px rgba(0,0,0,.25);font-size:14px;animation:fadeIn .2s;z-index:21}.ui-color-switch{position:absolute;top:12px;right:12px;color:#2a80eb;border:1px solid transparent;height:20px;line-height:20px;padding:2px 5px;border-radius:3px;background:none;font-family:inherit;transition:border-color .2s,background-color .2s;box-sizing:content-box}.ui-color-switch:hover{border-color:#d0d0d5;background-color:#fff}.ui-color-switch:active{line-height:normal}.ui-color-current{padding-bottom:20px}.ui-color-current-square{display:inline-block;width:20px;height:20px;margin-right:5px;border-radius:3px;box-shadow:inset 0 1px rgba(0,0,0,.25),inset 0 -1px rgba(0,0,0,.25),inset 1px 0 rgba(0,0,0,.25),inset -1px 0 rgba(0,0,0,.25);background-color:currentColor;vertical-align:middle}.ui-color-current-input{width:72px;border:1px solid #d0d0d5;background-color:#fff;height:20px;line-height:20px;padding:2px 5px;border-radius:3px;margin-left:5px;font-size:13px;vertical-align:middle;box-sizing:content-box;text-transform:uppercase;color:inherit}.ui-color-body{min-height:100px}.ui-color-basic{overflow:hidden}.ui-color-lump-group{width:72px;float:left}.ui-color-lump{display:block;width:11px;height:11px;margin:0 1px 1px 0;box-sizing:border-box;background-color:currentColor}.ui-color-basic a.active,.ui-color-lump:hover{border:1px solid #fff}.ui-color-basic-l{width:12px;float:left;overflow:hidden}.ui-color-basic-r{margin-left:25px;overflow:hidden}.ui-color-basic-r .ui-color-lump{float:left}.ui-color-more{display:none;height:100px}.ui-color-more svg{width:100%;height:100%}.ui-color-more-l{width:180px;height:inherit;float:left;position:relative}.ui-color-cover-white{background-color:transparent;background-image:linear-gradient(180deg,transparent,grey);filter:progid:DXImageTransform.Microsoft.gradient(startcolorstr=#00808080,endcolorstr=#FF808080,gradientType=0);cursor:crosshair}.ui-color-circle{position:absolute;left:0;top:0;width:16px;height:16px;border:3px solid #fff;border-radius:20px;background-color:red;background-clip:content-box;-ms-transform:translate(-11px,-11px);transform:translate(-11px,-11px)}.ui-color-more-r{height:inherit;float:right;padding-right:8px;position:relative}.ui-color-more-fill{display:block;width:16px;height:100%;background-color:red}.ui-color-cover-white,.ui-color-more-cover{position:absolute;left:0;top:0;width:inherit;height:100px}.ui-color-more-cover{background-color:rgba(0,0,0,.01);-webkit-tap-highlight-color:transparent}.ui-color-more-arrow{position:absolute;right:0;top:100%}.ui-color-more-arrow:before{content:"";position:absolute;right:0;top:-5px;width:0;height:0;border-color:transparent #36383f transparent transparent;border-style:solid;border-width:5px 6px;overflow:hidden}.ui-color-footer{margin-top:15px;padding-bottom:5px;text-align:right}.ui-color-button-cancel,.ui-color-button-ensure{display:inline-block;width:80px;line-height:20px;padding-top:8px;padding-bottom:8px;margin-left:15px;border-radius:4px;text-align:center;font-size:14px;font-family:inherit;transition:box-shadow .2s,border-color .2s;cursor:pointer}.ui-color-button-cancel{border:1px solid #d0d0d5;background-color:#fff;color:#4c5161}.ui-color-button-cancel:hover{border-color:#ababaf;color:#4c5161}.ui-color-button-ensure{border:1px solid #2a80eb;background-color:#2a80eb;color:#fff}.ui-color-button-ensure:hover{color:#fff}.ui-color-button-cancel:hover,.ui-color-button-ensure:hover{box-shadow:inset 0 1px 2px rgba(0,0,0,.01),inset 0 0 0 100px rgba(0,0,0,.05)}.ui-color-button-cancel:active,.ui-color-button-ensure:active{box-shadow:inset 0 1px 2px rgba(0,0,0,.1),inset 0 0 0 100px rgba(0,0,0,.1)}datalist{display:none}.ui-datalist{display:none;position:absolute;animation:fadeIn .2s;z-index:19}.ui-datalist-datalist{max-height:304px;background-color:#fff;box-shadow:0 2px 5px rgba(0,0,0,.25);margin:0;padding:0;list-style:none;border:1px solid #d0d0d5;border:0 rgba(0,0,0,.2);font-size:14px;position:relative;overflow:auto;overscroll-behavior:none;-ms-scroll-chaining:none}.ui-datalist-datalist::-webkit-scrollbar{width:8px;height:8px}.ui-datalist-datalist::-webkit-scrollbar-thumb{background-color:#bbb;border-radius:8px}.ui-datalist-datalist::-webkit-scrollbar-thumb:hover{background-color:#aaa}.ui-datalist-datalist::-webkit-scrollbar-track-piece{background-color:#ddd}.ui-datalist-option{line-height:20px;padding:9px 12px;background-color:#fff;transition:background-color .15s;overflow:hidden;cursor:pointer}.ui-datalist-option:empty,.ui-datalist:empty{display:none}.ui-datalist-option:not(.disabled):hover{background-color:#f0f7ff}.ui-datalist-datalist>.selected{background-color:#e0f0ff}.ui-datalist-datalist>.disabled{opacity:.4;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.ui-datalist-value{display:block;text-overflow:ellipsis;white-space:nowrap;color:inherit;overflow:hidden}.ui-datalist-label{float:right;color:#a2a9b6;font-size:12px}.ui-datalist-label+.ui-datalist-value{margin-right:60px}::-webkit-calendar-picker-indicator,::-webkit-clear-button,::-webkit-inner-spin-button{display:none}[type=date]::-webkit-datetime-edit-text{color:transparent;background:linear-gradient(180deg,transparent 9px,#4c5161 0,#4c5161 10px,transparent 0) no-repeat 50%;background-size:80% 100%}::-webkit-datetime-edit-ampm-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{background:none;color:#4c5161}:disabled::-webkit-datetime-edit-ampm-field,:disabled::-webkit-datetime-edit-day-field,:disabled::-webkit-datetime-edit-hour-field,:disabled::-webkit-datetime-edit-minute-field,:disabled::-webkit-datetime-edit-month-field,:disabled::-webkit-datetime-edit-text,:disabled::-webkit-datetime-edit-year-field{opacity:.4}:valid::-webkit-datetime-edit{visibility:hidden}.ui-date-input,.ui-date-range-input,.ui-month-input,.ui-month-range-input,.ui-time-input,.ui-year-input{-webkit-tap-highlight-color:transparent;position:relative}[class].ui-date-input>input,[class].ui-date-range-input>input,[class].ui-hour-input>input,[class].ui-month-input>input,[class].ui-month-range-input>input,[class].ui-time-input>input,[class].ui-year-input>input{font-family:Helvetica Neue,Helvetica,Arial,sans-serif;background:#fff;-webkit-appearance:none}.ui-input:hover>input[readonly]{border-color:#ababaf}.ui-input:active>input[readonly]{background-color:#f7f9fa}span.ui-date-input>input{width:125px}span.ui-time-input>input,span.ui-year-input>input{width:85px}span.ui-month-input>input{width:125px}span.ui-date-range-input>input{width:210px}span.ui-month-range-input>input{width:170px}@supports (-webkit-appearance:none) or (-moz-appearance:none){span.ui-time-input>[type=time]{width:auto;max-width:125px}}@supports not (-moz-appearance:none){span.ui-time-input>[type=time]{padding-right:33px}}.ui-date-arrow{position:absolute;left:0;right:0;top:0;bottom:0;border-right:4px solid transparent;cursor:pointer}.ui-date-arrow:before{content:"";position:absolute;width:20px;top:1px;bottom:1px;right:0;margin:auto;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-205 297 200 200'%3E%3Cpath d='M-59.3 365.9c-5.1-5.2-13.4-5.2-18.5 0l-27.7 28.3-27.7-28.3c-5.1-5.2-13.4-5.2-18.5 0s-5.1 13.6 0 18.9l46.2 47.1 46.2-47.1c5.1-5.2 5.1-13.6 0-18.9z' fill='%232a80eb'/%3E%3C/svg%3E") no-repeat 100%;background-size:20px 20px}:disabled+.ui-date-arrow{cursor:default}:disabled+.ui-date-arrow:before{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-205 297 200 200'%3E%3Cpath d='M-59.3 365.9c-5.1-5.2-13.4-5.2-18.5 0l-27.7 28.3-27.7-28.3c-5.1-5.2-13.4-5.2-18.5 0s-5.1 13.6 0 18.9l46.2 47.1 46.2-47.1c5.1-5.2 5.1-13.6 0-18.9z' fill='%232a80eb' fill-opacity='.4'/%3E%3C/svg%3E")}.ui-date-arrow:before{background-color:#fff;transition:background-color .15s}.ui-input:active .ui-date-arrow:before,:disabled+.ui-date-arrow:before{background-color:#f7f9fa}.ui-date-container{display:inline-block;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.25);border:1px solid #d0d0d5;border-radius:4px;font-size:14px;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;animation:fadeIn .2s}body>.ui-date-container{display:none;position:absolute;z-index:9}.ui-date-container a{text-decoration:none;transition:background-color .2s,color .2s}.ui-date-head{padding:5px 0 0;overflow:hidden}.ui-date-half{width:50%;float:left}.ui-date-next,.ui-date-prev{width:35px;height:30px;text-align:center;color:#b6bbc6;fill:currentColor}a.ui-date-prev:hover{color:#2a80eb}span.ui-date-prev{color:#ccd0d7}a.ui-date-next:hover{color:#2a80eb}span.ui-date-next{color:#ccd0d7}.ui-date-next>svg,.ui-date-prev>svg{display:block;width:20px;height:20px;margin:5px auto 0}.ui-date-next>svg{-ms-transform:rotate(180deg);transform:rotate(180deg)}.ui-date-prev{float:left}.ui-date-next{float:right}.ui-date-switch{display:block;line-height:30px;margin:0 35px;border-radius:2px;color:#4c5161;text-align:center}a.ui-date-item:not(.selected):hover,a.ui-date-switch:hover{color:#4c5161;background-color:#f0f0f2}.ui-date-x,.ui-hour-x,.ui-minute-x,.ui-month-x,.ui-year-x{width:225px}.ui-minute-x[data-step="1"]{width:328px}.ui-minute-x[data-step="2"]{width:276px}.ui-minute-body{padding-left:12px;padding-bottom:12px}.ui-hour-body{padding:8px 0 12px 12px}.ui-date-body,.ui-month-body,.ui-year-body{padding-left:5px;padding-right:2px;padding-bottom:5px}.ui-date-item{display:inline-block;border-radius:2px;text-align:center;font-size:13px;color:#4c5161}span.ui-date-item{opacity:.4}.ui-date-item.col0,.ui-date-item.col6,.ui-day-item.col0,.ui-day-item.col6{color:#eb4646}.ui-date-tr:last-child .ui-date-item:empty{display:none}.ui-hour-body .ui-date-item,.ui-minute-body .ui-date-item{width:45px;line-height:26px;margin-top:4px;margin-right:7px}.ui-month-body .ui-date-item,.ui-year-body .ui-date-item{width:45px;line-height:54px;margin-top:5px;margin-left:7px}.ui-date-now{display:block;line-height:30px;margin:0 5px 5px;text-align:center}.ui-day-x{padding:0 2px 0 5px;text-align:center}.ui-date-body .ui-date-item,.ui-day-item{display:inline-block;width:28px;line-height:28px;margin-right:3px;margin-top:1px;vertical-align:top}.ui-range-x{width:458px}.ui-range-body{overflow:hidden}.ui-range-body .ui-date-half+.ui-date-half{border-left:1px solid #f0f0f2;margin-left:-1px}.ui-range-footer{padding:5px 15px 15px;text-align:right}.ui-range-footer>.ui-button{margin-left:10px}.ui-date-container .selected{background-color:#2a80eb;color:#fff;cursor:default}.ui-date-container span.selected{opacity:.4}.ui-range-body .ui-date-half{width:229px}.ui-range-body .ui-date-body{padding-left:6px;padding-right:0}.ui-range-body .ui-month-body{margin-bottom:15px}.ui-range-date-body .selected{width:26px;line-height:26px;border:1px solid #2a80eb;border-right-width:4px;margin-right:0;border-radius:0}.ui-range-body .selected.col0{margin-left:-6px;border-left-width:7px}.ui-range-body .selected.col6{border-right-width:10px}.ui-range-body .selected.ui-date-first:not(.col0){border-top-left-radius:2px;border-bottom-left-radius:2px}.ui-range-body .selected.ui-date-last:not(.col6){border-top-right-radius:2px;border-bottom-right-radius:2px}.ui-range-body .ui-date-begin,.ui-range-body .ui-date-end{border-radius:0;width:26px;background-color:#fff;color:#4c5161}.ui-range-body .ui-date-begin{border-right-width:4px;border-left-width:1px;border-top-left-radius:2px;border-bottom-left-radius:2px}.ui-range-body .ui-date-end{margin-right:3px;border-right-width:1px;border-top-right-radius:2px;border-bottom-right-radius:2px}.ui-range-body .ui-date-begin:hover,.ui-range-body .ui-date-end:hover{background-color:#fff;color:#4c5161}.ui-range-body .ui-date-begin.col6{border-right-width:0;padding-right:9px}.ui-range-body .ui-date-begin.col0{border-left-width:1px;margin-left:0}.ui-range-body .ui-date-end.col0{border-left-width:0;padding-left:7px}.ui-range-body .ui-date-end.col6{border-right-width:1px}.ui-range-body .ui-date-begin.ui-date-end{margin-right:3px;padding:0;border:1px solid #2a80eb;border-radius:2px}.ui-range-body .ui-date-begin+.ui-date-end{border-left-width:1px;margin-right:3px}.ui-dialog-container{position:fixed;left:0;top:0;height:100%;width:100%;padding:0;border:0;background-color:rgba(25,28,34,.88);text-align:center;color:#4c5161;font-size:14px;white-space:nowrap;overflow:auto;z-index:19}.ui-dialog-container:not([open]){display:none}.ui-dialog-animation{animation:fadeIn .2s both}.ui-dialog-container+.ui-dialog-container{transition:background-color .2s;background-color:transparent}.ui-dialog-container:after{content:"";height:95%}.ui-dialog,.ui-dialog-container:after{display:inline-block;vertical-align:middle}.ui-dialog{margin-top:20px;margin-bottom:30px;text-align:left;min-width:400px;border-radius:4px;background-color:#f7f9fa;white-space:normal;outline:none;position:relative}.ui-dialog-animation .ui-dialog{animation:tinydown .25s}.ui-dialog-title{margin:0;line-height:30px;padding:15px 50px 0 25px;font-weight:700;font-size:14px;color:#4c5161;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default}.ui-dialog-close{position:absolute;top:8px;right:7px;width:40px;height:40px;border:0;background:none;transition:fill .2s;fill:#b6bbc6;cursor:pointer;z-index:1}.ui-dialog-close>svg{width:20px;height:20px}.ui-dialog-close:hover{background-color:#4c5161;background-color:transparent;fill:#4c5161}.ui-dialog-body{min-height:60px;padding:10px 25px 20px}.ui-dialog-title:empty~.ui-dialog-body{min-height:40px;padding-top:30px}.ui-dialog-body:after{content:"";display:table;clear:both}.ui-dialog-footer{padding:3px 25px 25px;margin-top:-3px;text-align:right;max-height:40px;opacity:1;transition:max-height .2s,opacity .2s .1s;overflow:hidden}.ui-dialog-footer:empty{max-height:0;opacity:0}.ui-dialog-footer .ui-button{margin-left:15px}.ui-dialog-footer .ui-button:first-child{margin-left:0}.ui-dialog-stretch{max-height:2000px;height:calc(100% - 50px)}.ui-dialog-stretch .ui-dialog-footer{position:absolute;left:0;bottom:0;right:0}.ui-dialog-stretch .ui-dialog-body{position:absolute;left:0;right:0;top:50px;bottom:90px;padding:0 0 0 25px;overflow:auto}.ui-dialog-remind{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-105 197 400 400'%3E%3Cpath d='M95.5 197.5c110.5 0 200 89.5 200 200s-89.5 200-200 200-200-89.5-200-200 89.5-200 200-200z' fill='%232a80eb'/%3E%3Cpath d='M90.5 347.5h10c2.8 0 5 2.2 5 5v150c0 2.8-2.2 5-5 5h-10c-2.8 0-5-2.2-5-5v-150c0-2.8 2.2-5 5-5zm0-50h10c2.8 0 5 2.2 5 5v20c0 2.8-2.2 5-5 5h-10c-2.8 0-5-2.2-5-5v-20c0-2.8 2.2-5 5-5z' fill='%23fff'/%3E%3C/svg%3E"),none}.ui-dialog-success{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400'%3E%3Cpath fill='%231cad70' d='M400.5 200.5c0 110.457-89.542 199.999-199.999 199.999C90.043 400.499.5 310.957.5 200.5m0 0C.5 90.042 90.043.5 200.501.5 310.958.5 400.5 90.042 400.5 200.5'/%3E%3Cpath fill='%23FFF' d='M286.398 147.132c-1.654-1.134-3.306-2.395-6.801-4.293-4.271-2.336-9.259 2.624-12.391 6.816l-77.641 102.279-47.916-63.522c-3.144-4.188-4.902-8.468-13.073-1.859-3.097 2.123.234-.361-3.969 2.881-3.884 3.064-4.105 8.598-.971 12.774 0 0 38.641 55.817 45.883 65.074 10.625 13.22 29.944 12.57 40.087 0 7.483-9.473 77.757-107.584 77.757-107.584 3.14-4.194 2.898-9.697-.965-12.566z'/%3E%3C/svg%3E"),none}.ui-dialog-warning{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400'%3E%3Cpath fill='%23f59b00' d='M400.5 200.5c0 110.457-89.542 199.999-199.999 199.999C90.043 400.499.5 310.957.5 200.5m0 0C.5 90.042 90.043.5 200.501.5 310.958.5 400.5 90.042 400.5 200.5'/%3E%3Cpath fill='%23FFF' d='M195.503 100.503h10a5 5 0 015 5v150a5 5 0 01-5 5h-10a5 5 0 01-5-5v-150a5 5 0 015-5zm0 179.999h10a5 5 0 015 4.999v20.002a5 5 0 01-5 5h-10a5 5 0 01-5-5v-20.002a5 5 0 015-4.999z'/%3E%3C/svg%3E"),none}.ui-dialog-danger{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400'%3E%3Cpath fill='%23eb4646' d='M400.5 200.5c0 110.457-89.542 199.999-199.999 199.999C90.043 400.499.5 310.957.5 200.5m0 0C.5 90.042 90.043.5 200.501.5 310.958.5 400.5 90.042 400.5 200.5'/%3E%3Cpath fill='%23FFF' d='M195.503 100.503h10a5 5 0 015 5v150a5 5 0 01-5 5h-10a5 5 0 01-5-5v-150a5 5 0 015-5zm0 179.999h10a5 5 0 015 4.999v20.002a5 5 0 01-5 5h-10a5 5 0 01-5-5v-20.002a5 5 0 015-4.999z'/%3E%3C/svg%3E"),none}.ui-dialog-alert,.ui-dialog-confirm{max-width:340px;min-height:40px;padding-top:10px;font-size:16px;word-wrap:break-word;overflow:hidden}.ui-dialog-danger,.ui-dialog-remind,.ui-dialog-success,.ui-dialog-warning{padding:20px 0 20px 60px;background-repeat:no-repeat;background-position:0 10px;background-size:40px 40px}.ui-dialog-alert>h6,.ui-dialog-confirm>h6{font-size:15px;margin-bottom:5px}.ui-dialog-alert>:first-child:only-child,.ui-dialog-confirm>:first-child:only-child{margin-top:0}.ui-dialog-alert>:first-child:not(:only-child),.ui-dialog-confirm>:first-child:not(:only-child){margin-top:-10px}.ui-dialog-alert>h6~p,.ui-dialog-confirm>h6~p{font-size:14px}.ui-dialog-alert>p,.ui-dialog-confirm>p{margin:0}.ui-dialog-loading .ui-dialog-close,.ui-dialog-loading .ui-dialog-footer,.ui-dialog-loading .ui-dialog-title{visibility:hidden}.ui-dialog-loading .ui-dialog-body{min-width:400px}@media screen and (max-width:480px){.ui-dialog,.ui-dialog-loading .ui-dialog-body{min-width:90vw}.ui-dialog-danger,.ui-dialog-remind,.ui-dialog-success,.ui-dialog-warning{padding-bottom:0}.ui-dialog-container-alert .ui-dialog,.ui-dialog-container-confirm .ui-dialog,.ui-dialog[style*="width: auto"]{max-width:calc(100vw - 16px)}}.ui-droplist-x{position:absolute;width:111px;padding:7px 0;background-color:#fff;box-shadow:0 2px 5px rgba(0,0,0,.25);border:1px solid #d0d0d5;border-radius:4px;font-size:14px;animation:fadeIn .2s;z-index:9}.ui-droplist-li{display:block;line-height:20px;padding:7px 12px 8px;color:#4c5161;text-decoration:none;cursor:pointer;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.ui-droplist-hr{border:0;border-bottom:1px solid #d0d0d5;margin:7px 12px;opacity:.4}a.ui-droplist-li:hover{color:#4c5161;background-color:#f0f7ff}a.ui-droplist-li:hover:after{background-position:0 -20px}span.ui-droplist-li{color:#a2a9b6;cursor:default}.ui-droplist-li[data-sublist]:before{-ms-transform:rotate(-90deg);transform:rotate(-90deg);margin-top:1px;float:right}.ui-droplist-x>.selected{background-color:#f1f9fe}.selected+.ui-droplist-xx>.ui-droplist-x{display:block}.ui-droplist-xx{position:relative}.ui-droplist-xx>.ui-droplist-x{display:none;left:calc(100% - 5px);top:-35px}.ui-droplist-xx>.reverse{left:auto;right:calc(100% - 5px)}.ui-droplist-arrow:empty,.ui-droplist-arrow:not(:empty):after,.ui-droplist-li[data-sublist]:before{content:"";display:inline-block;width:20px;height:20px;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-205 197 200 400'%3E%3Cpath d='M-59.7 271.6c-4.2-4.1-11-4.1-15.3 0l-30.5 29.6-30.5-29.6c-4.2-4.1-11-4.1-15.3 0-4.2 4.1-4.2 10.7 0 14.8l38.2 37c4.2 4.1 11 4.1 15.3 0l38.2-37c4.1-4.1 4.1-10.7-.1-14.8z' fill='%23a2a9b6'/%3E%3Cpath d='M-58.7 471.6c-4.2-4.1-11-4.1-15.3 0l-30.5 29.6-30.5-29.6c-4.2-4.1-11-4.1-15.3 0-4.2 4.1-4.2 10.7 0 14.8l38.2 37c4.2 4.1 11 4.1 15.3 0l38.2-37c4.1-4.1 4.1-10.7-.1-14.8z' fill='%232a80eb'/%3E%3C/svg%3E"),none;background-size:20px 40px;vertical-align:-5px}.ui-droplist-arrow:not(:empty):hover:after,a:hover .ui-droplist-arrow:empty{background-position:0 -20px}.ui-dropanel-x{position:absolute;width:260px;padding:20px;background-color:#fff;box-shadow:0 1px 3px rgba(0,0,0,.25);border:1px solid #d0d0d5;border:0 rgba(0,0,0,.2);font-size:14px;animation:fadeIn .2s;z-index:9}.ui-dropanel-title{line-height:20px;margin-top:-2px;margin-bottom:0;font-size:14px;font-weight:700}.ui-dropanel-close{position:absolute;top:3px;right:2px;width:40px;height:40px;border:0;background:none;margin:0;padding:0;transition:fill .2s;fill:#b6bbc6;cursor:pointer;z-index:1}.ui-dropanel-close svg{width:20px;height:20px}.ui-dropanel-close:hover{background-color:#4c5161;fill:#4c5161;background:none,none}.ui-dropanel-content{display:block;min-height:40px;padding:10px 0 20px}.ui-dropanel-footer{text-align:right}.ui-dropanel-footer .ui-button{margin-left:15px}.ui-dropanel-footer .ui-button:first-child{margin-left:0}input:not([type=search])::-ms-clear{display:none}[type=search]{-webkit-appearance:none}[type=search]::-webkit-search-cancel-button{-webkit-appearance:none;width:20px;height:20px;margin-right:-2px;background:#b6bbc6 url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMDAiIGhlaWdodD0iMjAwIj48cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZmlsbD0iI0ZGRiIgZD0iTTAgMHYyMDBoMjAwVjBIMHptMTUxLjYzNiAxMzYuNDgyYTcuMzc0IDcuMzc0IDAgMDEwIDEwLjQyN2wtNS4yMTIgNS4yMWE3LjM3MiA3LjM3MiAwIDAxLTEwLjQyNiAwbC0zNi40ODMtMzYuNDg1TDYzLjAzIDE1Mi4xMmE3LjM3IDcuMzcgMCAwMS0xMC40MjQgMGwtNS4yMS01LjIxYTcuMzcgNy4zNyAwIDAxMC0xMC40MjhMODMuODggMTAwIDQ3LjM5NiA2My41MTRhNy4zNjggNy4zNjggMCAwMTAtMTAuNDI1bDUuMjEtNS4yMWE3LjM2OCA3LjM2OCAwIDAxMTAuNDI2IDBMOTkuNTE2IDg0LjM2IDEzNiA0Ny44OGE3LjM3IDcuMzcgMCAwMTEwLjQyNSAwbDUuMjEyIDUuMjFhNy4zNyA3LjM3IDAgMDEwIDEwLjQyNUwxMTUuMTUzIDEwMGwzNi40ODMgMzYuNDgyeiIvPjwvc3ZnPg==) no-repeat 50%;background-size:20px 20px;-webkit-transition:background-color .15s;transition:background-color .15s;cursor:pointer}[type=search]::-webkit-search-cancel-button:hover{background-color:#4c5161}input[type=search]::-webkit-search-results-decoration{display:none}input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #fff inset;background-color:transparent}input[disabled],input[readonly]{cursor:default}.ui-input>input,input.ui-input{height:40px;line-height:20px;padding:9px 8px;border:1px solid #d0d0d5;border-radius:4px;background-color:#fff;box-sizing:border-box;font-size:14px;outline:none;color:#4c5161;transition:border-color .15s,background-color .15s}.ui-input:hover,.ui-input:hover>input{border-color:#ababaf}.ui-input:focus,.ui-input>input:focus{border-color:#2a80eb}span.ui-input{display:inline-block}div.ui-input>input,input[width="100%"]{width:100%}.ui-input-x{padding:0 56px 0 3px;border-radius:4px;overflow:hidden}.ui-input-x,.ui-input-x>input{position:relative;box-sizing:border-box}.ui-input-x>input{display:block;width:100%;height:40px;line-height:20px;padding:9px 0;border-bottom:0;border-top:0;border-color:transparent currentcolor;border-style:solid none;border-width:1px 0;right:-6px;color:#4c5161;font-size:14px;outline:none;background:none;background-clip:content-box;z-index:1}.ui-input-x>.ui-input{position:absolute;border:1px solid #d0d0d5;border-radius:4px;background-color:#fff;top:0;bottom:0;left:0;right:0;transition:border-color .15s,background-color .15s}.ui-input-x .ui-input-count{line-height:38px;padding:0 2px;color:#a2a9b6;font-size:12px;white-space:nowrap;position:absolute;font-family:sans-serif;right:8px;top:1px;z-index:1}.ui-input-count slash{margin:0 1px}.ui-input-x>input:not(:disabled):not([readonly]):hover~.ui-input{border-color:#ababaf}.ui-input-x>input:not(:disabled):not([readonly]):focus~.ui-input{border-color:#2a80eb}.ui-input-x .ui-placeholder{padding:9px 7px;z-index:1}.ui-input-search:not(input){position:relative}.ui-input-search>input:not(.ui-icon-search){padding-left:40px}.ui-input-search[align=right]>:not(.ui-icon-search){padding-right:40px;padding-left:9px}.ui-icon-search{position:absolute;left:3px;top:1px;width:20px;height:20px;color:#b6bbc6;background-color:transparent;border:solid transparent;border-width:9px 8px;box-sizing:content-box;transition:color .2s;padding:0;margin:0;text-indent:-99px;font-size:0;cursor:pointer;outline:0 none;overflow:hidden}[align=right]>.ui-icon-search{left:auto;right:3px}.ui-input-search:hover .ui-icon-search{color:#a2a9b6}.ui-input-search>:disabled~.ui-icon-search{color:#b6bbc6;cursor:default}.ui-input-search>:focus~.ui-icon-search{color:#2a80eb}.ui-input-search>.error~.ui-icon-search{color:#eb4646}.ui-icon-search:after,.ui-icon-search:before{content:"";position:absolute}.ui-icon-search:before{width:9px;height:9px;border:2px solid;border-radius:50%;left:2px;top:2px}.ui-icon-search:after{width:6px;border-top:2px solid;transform-origin:left;transform:scaleY(1.25) rotate(30deg);left:13px;top:11px}input.ui-icon-search{border:0;margin:1px;width:18px;height:18px;background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M638.72 638.72a256 256 0 10-361.984-361.984A256 256 0 00638.72 638.72zm58.71 119.04a384 384 0 1185.418-95.573l202.24 202.24a64.256 64.256 0 01.597 91.136 63.744 63.744 0 01-91.05-.598l-197.206-197.12z' fill='%23b6bbc6'/%3E%3C/svg%3E") 50%;background-clip:content-box;background-size:17.9px 17.9px;box-sizing:content-box}:focus~input.ui-icon-search{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M638.72 638.72a256 256 0 10-361.984-361.984A256 256 0 00638.72 638.72zm58.71 119.04a384 384 0 1185.418-95.573l202.24 202.24a64.256 64.256 0 01.597 91.136 63.744 63.744 0 01-91.05-.598l-197.206-197.12z' fill='%232a80eb'/%3E%3C/svg%3E")}.error~input.ui-icon-search{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M638.72 638.72a256 256 0 10-361.984-361.984A256 256 0 00638.72 638.72zm58.71 119.04a384 384 0 1185.418-95.573l202.24 202.24a64.256 64.256 0 01.597 91.136 63.744 63.744 0 01-91.05-.598l-197.206-197.12z' fill='%23eb4646'/%3E%3C/svg%3E")}.ui-input-x>:disabled~.ui-input,.ui-input>input:disabled,input.ui-input:disabled{background-color:#f7f9fa}.ui-input-x>input:disabled,.ui-input>input:disabled,input.ui-input:disabled{color:#a2a9b6}.ui-input:disabled:hover,.ui-input:hover>input:disabled,.ui-input>input:disabled:hover,.ui-input>input[readonly]:focus,.ui-input>input[readonly]:hover,.ui-input[readonly]:focus,.ui-input[readonly]:hover{border-color:#d0d0d5}.ui-input.error,.ui-input>.error{border-color:#eb4646!important}.ui-input-count.error,.ui-input-count>.error{color:#eb4646}.ui-kbd-tips{position:absolute;left:-9em;top:-9em;font-family:consolas,Liberation Mono,courier,monospace;font-size:12px;border-radius:2px;color:#fff;background:rgba(0,0,0,.75);opacity:.8;line-height:13px;padding:0 3px;z-index:99}.ui-kbd-tips kbd{font-family:inherit}.ui-outline.ui-outline{outline:1px dotted #2a80eb;outline:5px auto -webkit-focus-ring-color}.ui-lightip{display:none;width:25em;margin:0 auto;border-radius:2px;text-align:center;font-size:14px;line-height:20px;padding:15px 1em;background-color:#4c5161;animation:fadeIn .25s both;position:fixed;top:0;left:1rem;right:1rem;z-index:19;outline:none;cursor:default}.ui-lightip[open]{display:inline}.ui-lightip[data-status=success]{background-color:#1cad70}.ui-lightip[data-status=error]{background-color:#eb4646}.ui-lightip-text{display:inline-block;background-repeat:no-repeat;background-size:20px 20px;text-align:left;color:#fff}[data-status=success] .ui-lightip-text{padding-left:23px;margin-left:-5px;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath fill='%23FFF' d='M163.038 57.226c-5.217-4.162-5.713-4.289-11.674-7.244-2.683-1.344-6.633 2.113-8.569 4.67l-52.648 67.042-34.301-43.387c-1.94-2.558-5.516-3.499-8.2-2.293-6.11 3.095-5.496 2.992-10.715 7.029-2.386 1.883-2.535 5.245-.597 7.793 0 0 36.97 46.917 41.44 52.565 6.557 8.068 18.483 7.669 24.744 0 4.62-5.781 61.117-78.506 61.117-78.506 1.937-2.559 1.788-5.918-.597-7.669z'/%3E%3C/svg%3E")}[data-status=error] .ui-lightip-text{padding-left:23px;margin-left:-5px;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath fill='%23FFF' d='M116.153 99.999l36.484-36.486a7.369 7.369 0 000-10.423l-5.212-5.213a7.375 7.375 0 00-10.425 0l-36.484 36.485-36.485-36.485a7.374 7.374 0 00-10.424 0l-5.211 5.213a7.365 7.365 0 000 10.423L84.88 99.999l-36.483 36.485a7.369 7.369 0 000 10.426l5.211 5.213a7.38 7.38 0 0010.424 0l36.485-36.486L137 152.122a7.38 7.38 0 0010.425 0l5.212-5.213a7.372 7.372 0 000-10.426l-36.484-36.484z'/%3E%3C/svg%3E")}@media screen and (max-width:640px){.ui-lightip{width:auto;top:50%;left:50%;right:auto;max-width:calc(100% - 2rem - 2em);transform:translate(-50%,-50%)}}.ui-loading,ui-loading{text-align:center;cursor:default;box-sizing:border-box}ui-loading{display:inline-block;font-size:14px;line-height:20px;vertical-align:middle}ui-loading[align=center]{position:absolute;left:50%;top:50%;-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%)}ui-loading:not([rows]):not([spin]):before,ui-loading[rows]{display:block}ui-loading:not([rows]):not([spin]):after{display:none}ui-loading[rows="2"]{height:40px}ui-loading[rows="3"]{height:60px}ui-loading[rows="4"]{height:80px}ui-loading[rows="5"]{height:100px}ui-loading[rows="6"]{height:120px}ui-loading[rows="7"]{height:140px}ui-loading[rows="8"]{height:160px}ui-loading[rows="9"]{height:180px}ui-loading[rows="10"]{height:200px}ui-loading[rows="11"]{height:220px}ui-loading[rows="12"]{height:240px}ui-loading[rows="13"]{height:260px}ui-loading[rows="14"]{height:280px}ui-loading[rows="15"]{height:300px}ui-loading[width="100%"]{width:100%}ui-loading[height="100%"]{height:100%}.ui-loading:after,ui-loading:after{content:"";display:inline-block;height:100%;vertical-align:middle}.ui-loading-before,.ui-loading:before,ui-loading:before{content:"";display:inline-block;width:20px;height:20px;margin:0 .5em;background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M512 1024q-104 0-199-40-92-39-163-110T40 711Q0 616 0 512q0-15 10.5-25.5T36 476t25.5 10.5T72 512q0 90 35 171 33 79 94 140t140 95q81 34 171 34t171-35q79-33 140-94t95-140q34-81 34-171t-35-171q-33-79-94-140t-140-95q-81-34-171-34-15 0-25.5-10.5T476 36t10.5-25.5T512 0q104 0 199 40 92 39 163 110t110 163q40 95 40 199t-40 199q-39 92-110 163T711 984q-95 40-199 40z' fill='%232a80eb'/%3E%3C/svg%3E") no-repeat 50%;background-size:100%;animation:spin 1s linear infinite;vertical-align:-4px}.ui-loading[spin]:before,ui-loading[spin]:before{display:none}.ui-loading[size="1"]:before,[size="1"]>.ui-loading-before,ui-loading[size="1"]:before{width:10px;height:10px;vertical-align:0}.ui-loading[size="3"]:before,[size="3"]>.ui-loading-before,ui-loading[size="3"]:before{width:30px;height:30px;vertical-align:-8px}.ui-loading[size="4"]:before,[size="4"]>.ui-loading-before,ui-loading[size="4"]:before{width:40px;height:40px;vertical-align:-12px}ui-dot{display:inline-block;height:1em;line-height:1;text-align:left;vertical-align:-.25em;overflow:hidden}ui-dot:before{display:block;content:"...\A..\A.";white-space:pre-wrap;animation:dot 3s step-start infinite both}@keyframes dot{33%{transform:translateY(-2em)}66%{transform:translateY(-1em)}}ui-pagination{display:block;height:30px}.ui-page{display:inline-block;min-width:18px;padding-left:2px;padding-right:2px;margin-left:5px;margin-right:5px;height:28px;line-height:28px;border:1px solid transparent;text-align:center;color:#a2a9b6;font-size:14px;font-family:Helvetica Neue,Helvetica,Arial,sans-serif;transition:border-color .15s,background-color .15s;vertical-align:top;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;position:relative}span.ui-page{cursor:default}a.ui-page:hover{border-color:#b6bbc6;color:#a2a9b6;text-decoration:none}.ui-page>svg{width:20px;height:20px;margin-top:3px}.ui-page-next,.ui-page-prev{text-align:center;fill:currentColor;overflow:hidden}span.ui-page-next,span.ui-page-prev{color:#ccd0d7}.ui-page-next svg{-ms-transform:scaleX(-1);transform:scaleX(-1)}.ui-page-prev{margin-left:0}.ui-page-next{margin-right:0}.ui-page-ellipsis{display:inline-block}.ui-page-current{color:#fff;background-color:#2a80eb}.ui-page-text{color:#4c5161}.ui-page.loading>svg{visibility:hidden}.ui-page.loading:before{content:"";position:absolute;left:0;top:0;right:0;bottom:0;background-repeat:no-repeat;width:20px;height:20px;background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M512 1024q-104 0-199-40-92-39-163-110T40 711Q0 616 0 512q0-15 10.5-25.5T36 476t25.5 10.5T72 512q0 90 35 171 33 79 94 140t140 95q81 34 171 34t171-35q79-33 140-94t95-140q34-81 34-171t-35-171q-33-79-94-140t-140-95q-81-34-171-34-15 0-25.5-10.5T476 36t10.5-25.5T512 0q104 0 199 40 92 39 163 110t110 163q40 95 40 199t-40 199q-39 92-110 163T711 984q-95 40-199 40z' fill='%232a80eb'/%3E%3C/svg%3E") no-repeat 50%;background-size:20px 20px;margin:auto;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0)}to{transform:rotate(1turn)}}::-webkit-input-placeholder{-webkit-transition:opacity .15s;color:#a2a9b6;line-height:inherit;font-size:14px}:focus::-webkit-input-placeholder{opacity:.38}::-moz-placeholder{transition:opacity .15s;color:#a2a9b6;font-size:14px}:focus::-moz-placeholder{opacity:.38}::placeholder{transition:opacity .15s;color:#a2a9b6;font-size:14px}:focus::placeholder{opacity:.38}:-ms-input-placeholder{transition:opacity .15s;color:#a2a9b6!important;font-size:14px}:focus:-ms-input-placeholder{opacity:.38}.ui-progress{display:inline-block;width:10em;height:.25em;vertical-align:calc(.25em - 2px);border:0;background-color:#d0d0d5;color:#2a80eb;border-radius:1em;overflow:hidden}.ui-progress::-moz-progress-bar{background-color:#2a80eb}.ui-progress::-webkit-progress-bar{background-color:#d0d0d5}.ui-progress::-webkit-progress-value{background-color:#2a80eb}progress[width="100%"]{width:100%}.ui-progress:indeterminate::-moz-progress-bar{background-color:inherit}.ui-progress::-ms-fill{border:none}.ui-progress[role]{display:inline-block;position:relative;box-sizing:border-box}.ui-progress[aria-valuenow]:before{background-color:#2a80eb}.ui-progress[aria-valuenow]{background:#d0d0d5}.ui-progress[aria-valuenow]:before{content:"";display:block;height:100%}input[type=radio]:not(.ui-visible){position:absolute;opacity:0;width:20px;height:20px;cursor:pointer;z-index:-1}.ui-visible+.ui-radio{display:none}.ui-radio{display:inline-block;width:20px;height:20px;border:1px solid #d0d0d5;border-radius:50%;background-color:#fff;box-sizing:border-box;vertical-align:-.5ex;-webkit-user-select:none;-ms-user-select:none;user-select:none;transition:border-color .2s;overflow:hidden}.ui-radio+label{margin-left:5px}:not(:disabled)+.ui-radio:hover{border-color:#ababaf}:focus+.ui-radio{border-color:#2a80eb}.ui-radio:before{content:"";display:block;width:10px;height:10px;margin:4px auto 0;border-radius:50%;background-color:#2a80eb;visibility:hidden}:checked+.ui-radio:before{visibility:visible}:disabled+.ui-radio{border-color:#ababaf;opacity:.38}.error.ui-radio{border-color:#eb4646}.ui-range-input,[type=range]{height:20px;margin:0;padding:0;touch-action:none;visibility:hidden;vertical-align:middle}div.ui-range-input>input{width:100%;visibility:hidden}.ui-range-input[width="100%"]{width:100%}.ui-range{display:inline-block;visibility:visible;transition:opacity .2s}.ui-range-track{height:4px;margin-top:8px;border-radius:4px;background-color:#a2a9b6;border-left:0 solid #2a80eb;text-align:left}.ui-range-thumb{width:16px;height:16px;position:absolute;margin:-7px 0 0 -9px;border-radius:20px;background-color:#fff;box-shadow:0 1px 3px 1px rgba(0,0,0,.25);transition:border-color .15s,background-color .15s;cursor:pointer;-webkit-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}@media (any-pointer:coarse){.ui-range-thumb{width:20px;height:20px;margin:-9px 0 0 -11px}}.ui-range-thumb:hover{border-color:#ababaf}.ui-range-thumb.active{background-color:#f7f9fa;box-shadow:0 0 1px 1px rgba(0,0,0,.25)}:disabled+.ui-range{opacity:.38;cursor:default}:disabled+.ui-range .ui-range-track{position:relative}:disabled+.ui-range .ui-range-thumb{cursor:inherit}select{display:inline-block;height:40px;margin:0;border:1px solid #d0d0d5;border-right-width:27px;opacity:.0001;font-size:14px;font-family:simsun;vertical-align:middle}select[width="100%"]{width:100%}select[multiple]{height:auto;font-size:38px;font-size:33px;font-family:simsun;padding:0;border-right-width:1px;vertical-align:top;cursor:pointer}select[multiple]>option{min-height:38px;height:38px;padding:0;font-size:inherit}select[multiple]>option:disabled{cursor:default}select[hidden],select[hidden]+.ui-select{display:none}select.ui-visible,select[opacity="1"],select[opacity="100%"],select[style*="opacity:1"],select[style*="opacity: 1"]{opacity:1;border-right-width:1px}.ui-select{display:inline-block;height:40px;line-height:20px;vertical-align:middle;font-size:14px;transition:opacity .2s;position:relative}[multiple]~.ui-select{vertical-align:top}.ui-select.active{z-index:3}.ui-select-button{display:block;height:20px;padding:9px 27px 9px 12px;color:#4c5161;border:1px solid #d0d0d5;border-radius:4px;background-color:#fff;text-decoration:none;transition:border-color .15s,background-color .15s;cursor:pointer}.ui-select-button:hover{color:#4c5161;border-color:#ababaf}:not(:disabled)+.ui-select>.ui-select-button:active{background-color:#f7f9fa}.active>a.ui-select-button{border-color:#2a80eb;border-radius:4px 4px 0 0}.reverse>a.ui-select-button{border-radius:0 0 4px 4px}.ui-select-text{display:block;width:100%;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.ui-select-icon,.ui-select-text:only-child:after{position:absolute;width:20px;height:20px;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath fill='%232a80eb' d='M145.659 68.949a12.874 12.874 0 00-18.473 0L99.479 97.233 71.772 68.949a12.874 12.874 0 00-18.473 0c-5.099 5.208-5.099 13.648 0 18.857l46.18 47.14 46.181-47.14c5.099-5.208 5.099-13.649-.001-18.857z'/%3E%3C/svg%3E") no-repeat 50%;background-size:20px 20px;right:7px;top:10px}.ui-select-text:only-child:after{content:""}.ui-select-datalist{position:absolute;left:0;right:0;top:39px;display:none;max-height:304px;padding:0;border:1px solid #2a80eb;background-color:#fff;overflow:auto;overscroll-behavior:none;-ms-scroll-chaining:none}[multiple]~.ui-select>.ui-select-datalist{position:static;display:block;max-height:none;height:inherit;border-color:#d0d0d5;border-radius:4px;box-sizing:border-box}[multiple]:hover~.ui-select>.ui-select-datalist{border-color:#ababaf}[multiple]:focus~.ui-select>.ui-select-datalist{border-color:#2a80eb}.ui-select-datalist::-webkit-scrollbar{width:8px;height:8px}.ui-select-datalist::-webkit-scrollbar-thumb{background-color:#bbb;border-radius:8px}.ui-select-datalist::-webkit-scrollbar-thumb:hover{background-color:#aaa}.ui-select-datalist::-webkit-scrollbar-track-piece{background-color:#ddd}.active>.ui-select-datalist{display:block}.reverse>.ui-select-datalist{top:auto;bottom:39px}.ui-select-datalist-li{display:block;line-height:20px;padding:9px 12px;color:#4c5161;background-color:#fff;text-decoration:none;text-overflow:ellipsis;white-space:nowrap;transition:background-color .15s;overflow:hidden}.ui-select-datalist-li[href]{cursor:pointer}.ui-select-datalist-li:not(:only-child):empty{display:none}.ui-select-datalist-li:hover{color:#4c5161}.ui-select-datalist>.disabled{color:#a2a9b6;cursor:default}.ui-select-datalist>.selected{background-color:#e0f0ff}.ui-select-datalist-li[href]:hover,[multiple]~.ui-select .ui-select-datalist-li[href]{color:#4c5161;background-color:#f0f7ff}select:disabled{cursor:default}select:disabled+.ui-select{opacity:.38}select:disabled+.ui-select .ui-select-button,select:disabled+.ui-select .ui-select-datalist{cursor:default;border-color:#ababaf}.error .ui-select-button,.error[multiple]~.ui-select .ui-select-datalist,select.error{border-color:#eb4646}.ui-switch{display:inline-block;width:44px;height:26px;border:2px solid;border-radius:26px;background-color:currentColor;box-sizing:border-box;color:#b6bbc6;font-size:0;transition:all .2s;cursor:pointer;-webkit-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.ui-switch:before{content:"";display:block;width:22px;height:22px;border-radius:50%;background-color:#fff;transition:margin-left .2s}:active+.ui-switch:before{box-shadow:inset 1px 1px 1px rgba(0,0,0,.1)}:checked+.ui-switch{color:#2a80eb}:checked+.ui-switch:before{margin-left:18px}:disabled+.ui-switch{opacity:.38;cursor:default}.ui-switch:hover,:focus+.ui-switch{color:#a2a9b6}:checked+.ui-switch:hover,:checked:focus+.ui-switch{color:#0057c3}:disabled+.ui-switch:hover{color:#b6bbc6}:checked:disabled+.ui-switch:hover{color:#2a80eb}.ui-tab-tabs{height:40px;line-height:40px;border-bottom:1px solid #d0d0d5;position:relative}.ui-tab-tab{float:left;margin-right:50px;font-size:16px;text-align:center;color:#4c5161;text-decoration:none;overflow:hidden;cursor:pointer}.ui-tab-tab a{display:block;color:#4c5161}.ui-tab-tab:hover,.ui-tab-tab:hover a{color:#2a80eb}.ui-tab-tabs .active,.ui-tab-tabs .active:hover,.ui-tab-tabs .active a{line-height:36px;padding-top:2px;margin-bottom:-1px;border-bottom:3px solid;color:#2a80eb;cursor:default}.ui-tab-line{display:none;position:absolute;bottom:-1px;left:0;width:0;border-bottom:3px solid #2a80eb;transition:all .35s}.ui-tab-tabs>.ui-tab-line~.ui-tab-tab{line-height:40px;padding-top:0;margin-bottom:0;border-bottom:0}.ui-tab-contents{margin-top:30px}.ui-tab-content:not([role]):not(:target),.ui-tab-content[role]:not(.active),.ui-tab-contents:target-within .ui-tab-content:not(:target){display:none}.ui-table{width:100%;line-height:21px;table-layout:fixed;border-spacing:0;border-collapse:collapse\9;font-size:14px;border:1px solid #d0d0d5}.ui-table th,.ui-table thead td{background-color:#f7f9fa;border-bottom:1px solid #ededed;font-weight:400;font-style:normal;margin:0}.ui-table th:not([class]):not([align]),.ui-table thead td:not([class]):not([align]){text-align:left}.ui-table tbody td{background-color:#fff;border-bottom:1px solid #ededed}.ui-table td,.ui-table th{padding-top:14px;padding-bottom:14px;padding-right:20px}.ui-table td:first-child,.ui-table th:first-child{padding-left:20px}.ui-table tr{cursor:default}.ui-table tr:last-child td{padding-bottom:15px;border-bottom:0}.ui-table~.ui-loading{height:300px}textarea{font-family:inherit}.ui-textarea>textarea,textarea.ui-textarea{line-height:20px;padding:9px 8px;border:1px solid #d0d0d5;border-radius:4px;background-color:#fff;outline:none;color:#4c5161;font-size:14px;transition:border-color .15s,background-color .15s;word-break:break-all;vertical-align:top;box-sizing:border-box;resize:none;overflow:auto}textarea[resize]{resize:both}textarea[resize=vertical]{resize:vertical}textarea[resize=horizontal]{resize:horizontal}div.ui-textarea>textarea{width:100%}.ui-textarea:hover,.ui-textarea>textarea:hover{border-color:#ababaf}.ui-textarea:focus,.ui-textarea>textarea:focus{border-color:#2a80eb}.ui-textarea-x{position:relative;padding:2px 9px 32px 3px;border-radius:4px;box-sizing:border-box;overflow:hidden}.ui-textarea-x>textarea{display:block;width:100%;line-height:20px;border:0;padding:7px 0 9px;right:-6px;color:#4c5161;font-size:14px;outline:none;background:none;word-break:break-all;overflow:auto;resize:none;position:relative;z-index:1}.ui-textarea-x>.ui-textarea{position:absolute;border:1px solid #d0d0d5;border-radius:4px;background-color:#fff;top:0;bottom:0;left:0;right:0;transition:border-color .15s,background-color .15s}.ui-textarea-x .ui-textarea-count{position:absolute;left:8px;right:10px;bottom:0;line-height:32px;color:#a2a9b6;font-size:12px;text-align:right;z-index:1}.ui-textarea-count slash{margin:0 1px}.ui-textarea-x:hover>.ui-textarea{border-color:#ababaf}.ui-textarea-x>textarea:focus~.ui-textarea{border-color:#2a80eb}.ui-textarea-x .ui-placeholder{padding:7px!important;z-index:1}.ui-textarea-resize{width:17px;height:17px;position:absolute;background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 1024 1024' xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cpath d='M765.558 510.004a93.65 93.65 0 10191.665 0 93.65 93.65 0 10-191.665 0zm0 311.456a93.65 93.65 0 10191.665 0 93.65 93.65 0 10-191.665 0zm-343.401 0a93.65 93.65 0 10191.665 0 93.65 93.65 0 10-191.665 0zm0-311.456a93.65 93.65 0 10191.665 0 93.65 93.65 0 10-191.665 0zM765.558 202.54a93.65 93.65 0 10191.665 0 93.65 93.65 0 10-191.665 0zM66.777 821.46a93.65 93.65 0 10191.665 0 93.65 93.65 0 10-191.665 0z' fill='%23BFBFBF'/%3E%3C/svg%3E") no-repeat 100% 100%;background-size:100%}.ui-textarea-x>textarea:disabled~.ui-textarea,.ui-textarea-x>textarea[readonly]~.ui-textarea,.ui-textarea:disabled,.ui-textarea>textarea:disabled,.ui-textarea>textarea[readonly],.ui-textarea[readonly]{background-color:#f7f9fa}.ui-textarea-x>[readonly]~.ui-textarea,.ui-textarea>textarea[readonly],.ui-textarea[readonly]{background-color:#fff}.ui-textarea:disabled:hover,.ui-textarea>textarea:disabled:hover,.ui-textarea>textarea[readonly]:focus,.ui-textarea>textarea[readonly]:hover,.ui-textarea[readonly]:focus,.ui-textarea[readonly]:hover{border-color:#d0d0d5}textarea:disabled,textarea[readonly]{resize:none}.ui-textarea.error,.ui-textarea>.error{border-color:#eb4646!important}.ui-textarea-count.error,.ui-textarea-count>.error{color:#eb4646}.ui-tips[data-title]{text-indent:0;position:relative;overflow:visible}.ui-tips[data-title]:after,.ui-tips[data-title]:before{position:absolute;left:50%;-ms-pointer-events:none;pointer-events:none;-ms-transform:translateX(-50%);transform:translateX(-50%);visibility:hidden}.ui-tips[data-title]:before{content:attr(data-title);bottom:calc(100% + 12px);max-width:250px;padding:6px 10px;line-height:18px;border-radius:3px;background-color:#373c42;text-align:left;color:#fff;font-size:12px;font-style:normal;white-space:nowrap}.ui-tips[data-title]:after{content:"";border:6px solid transparent;border-top-color:#373c42;bottom:100%}.ui-tips[data-title]:focus:after,.ui-tips[data-title]:focus:before,.ui-tips[data-title]:hover:after,.ui-tips[data-title]:hover:before{transition:visibility .1s .1s;visibility:visible}.ui-tips[data-title]:hover{outline:none}.reverse.ui-tips[data-title]:before{bottom:auto;top:calc(100% + 12px)}.reverse.ui-tips[data-title]:after{border-color:transparent transparent #373c42;bottom:auto;top:100%}.ui-tips-x{text-align:center;position:absolute;z-index:99}.ui-tips-content{display:block;max-width:20em;padding:6px 10px;line-height:18px;border-radius:3px;background-color:#373c42;color:#fff;font-size:12px;font-style:normal;text-align:left}.ui-tips-arrow{position:absolute;top:100%;left:calc(50% - 6px);border:6px solid transparent;border-top-color:#373c42}@media (any-hover:none){html{--hoverNone:"true"}}.ui-tips-x[data-direction=top]{margin-top:-12px}.ui-tips-x[data-direction=left]{margin-left:-12px}.ui-tips-x[data-direction=right]{margin-left:12px}.ui-tips-x[data-direction=bottom]{margin-top:12px}[data-direction=bottom] .ui-tips-arrow{top:-12px;border-color:transparent transparent #373c42}[data-direction=left] .ui-tips-arrow,[data-direction=right] .ui-tips-arrow{top:calc(50% - 6px)}[data-direction=left] .ui-tips-arrow{left:100%;border-color:transparent transparent transparent #373c42}[data-direction=right] .ui-tips-arrow{left:-12px;border-color:transparent #373c42 transparent transparent}[data-align="6-8"] .ui-tips-content,[data-align="8-6"] .ui-tips-content{max-width:600px}[data-align="2-3"] .ui-tips-content,[data-align="3-2"] .ui-tips-content{position:relative;left:10px}[data-align="1-4"] .ui-tips-content,[data-align="4-1"] .ui-tips-content{position:relative;left:-10px}.ui-tips-error:not(.none){animation:fadeIn .2s,fallDown .2s}.ui-tips-error .ui-tips-content{background-color:#eb4646}.ui-tips-error .ui-tips-arrow{border-top-color:#eb4646}.table-x{background-color:#fff;border:1px solid #d0d0d5}.table-x table{border:0}.table-error-x,.table-null-x{height:300px;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.table-error-x{line-height:300px}.table-null,.table-null-x:after{display:inline-block;vertical-align:middle}.table-null-x:after{content:"";width:0;height:100%}.table-null-x:empty:before{content:"暂无数据"}.table-error-x:empty:before{content:"数据获取失败"}.table-page-x{padding:10px 10px 10px 20px;margin-top:-1px;border-top:1px solid #ededed;background-color:#f7f9fa;position:relative;overflow:hidden}@media screen and (max-width:640px){.table-page-x{padding-left:10px;padding-right:5px}}.table-page-data{float:left;line-height:20px;padding-top:5px;font-size:14px}.table-page-total{margin:0 3px}.table-page-per{display:inline-block;margin-left:5px;cursor:pointer}.table-page-per:after{content:"";display:inline-block;width:20px;height:20px;background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-205 197 200 400'%3E%3Cpath d='M-59.7 271.6c-4.2-4.1-11-4.1-15.3 0l-30.5 29.6-30.5-29.6c-4.2-4.1-11-4.1-15.3 0-4.2 4.1-4.2 10.7 0 14.8l38.2 37c4.2 4.1 11 4.1 15.3 0l38.2-37c4.1-4.1 4.1-10.7-.1-14.8z' fill='%23a2a9b6'/%3E%3Cpath d='M-58.7 471.6c-4.2-4.1-11-4.1-15.3 0l-30.5 29.6-30.5-29.6c-4.2-4.1-11-4.1-15.3 0-4.2 4.1-4.2 10.7 0 14.8l38.2 37c4.2 4.1 11 4.1 15.3 0l38.2-37c4.1-4.1 4.1-10.7-.1-14.8z' fill='%232a80eb'/%3E%3C/svg%3E") no-repeat;background-size:20px 40px;vertical-align:-5px}.table-page-per:hover:after{color:#2a80eb;background-position:0 -20px}.table-page{float:right;padding-top:2px}.table-checkbox td:first-child,.table-checkbox th:first-child{width:20px;padding-right:0;padding-left:18px;text-align:right}.table-checkbox td:first-child+td,.table-checkbox th:first-child+th{padding-left:13px}.table-checkbox tr:hover td{background-color:#f0f7ff}.table-checkbox tr.selected td{background-color:#e0f0ff}.table-header{padding:12px 20px;border-bottom:1px solid #ededed}.table-title{line-height:56px;font-size:24px;margin:0}ul{margin:0;padding:0}li{list-style-type:none}body,html,nav,nav ul{height:100%;overflow:hidden}body{background-color:#eef0f5}.clearfix{*zoom:1}.clearfix:after,.clearfix:before{display:table;content:""}.clearfix:after{clear:both}body .ui-input>input,body input.ui-input{height:30px}body .ui-button{min-width:65px;line-height:10px}body button.ui-button,body input.ui-button{height:30px}.container .ui-switch{width:26px;height:16px}.container :checked+.ui-switch:before{margin-left:10px}.container .ui-switch:before{width:12px;height:12px}body .ui-lightip{width:20em;padding:10px 1em;opacity:.8}.container{height:100%;width:100%;position:relative;display:flex;justify-content:space-between}.container nav{flex:0 0 200px;height:auto;width:200px;position:relative}.container nav ul{padding:4px 2px 2px 0;overflow:auto}.container nav ul::-webkit-scrollbar{width:3px}.container nav ul::-webkit-scrollbar-thumb{border-radius:10px;background:#bcd}.container nav ul::-webkit-scrollbar-track{border-radius:0;background:#eef0f5}.container nav li{cursor:default;font-size:13px;height:40px;line-height:40px;padding-left:32px;position:relative;background:url(record.56e10638.svg) no-repeat 10px;background-size:15px;color:#666;border-left:3px solid #eef0f5;opacity:.6}.container nav li.home{background:url(home.3a7af05d.svg) no-repeat 10px;background-size:15px}.container nav li.net{background:url(recordFind.08a261bc.svg) no-repeat 10px;background-size:15px}.container nav li.active,.container nav li.mouse,.container nav li:hover{background-color:#bedff7;border-left:3px solid #51b0f5}.container nav li.active,.container nav li:hover{opacity:1;border-radius:2px}.container nav li:hover .option{cursor:pointer;position:absolute;width:18px;height:40px;right:43px;top:0;background:url(edit.e5e6ea37.svg) no-repeat 50%;background-size:15px;opacity:.5}.container nav li:hover .option:hover{opacity:.9}.container nav li .onoff{position:absolute;right:10px;top:4px}.container nav:after{content:"LnnCoCo";position:absolute;bottom:2px;left:2px;color:hsla(0,0%,80%,.6);font-size:12px;transform:scale(.9);cursor:default}.container main{flex:1}.container main .textarea{background-color:#fff;border:1px solid #ddd;border-radius:3px;height:98%;margin-top:3px;margin-right:3px;box-shadow:0 0 1px rgba(0,0,0,.1)}.container main .textarea textarea{height:100%;width:100%;border:none;outline:none;font-size:15px}.container main .textarea.local .CodeMirror:before{content:"";position:absolute;width:50%;height:62%;right:5px;bottom:5px;opacity:.06;background:url(record.56e10638.svg) no-repeat 100% 100%;background-size:contain}.container main .textarea.net .CodeMirror:before{content:"";position:absolute;width:50%;height:62%;right:5px;bottom:5px;opacity:.06;background:url(recordFind.08a261bc.svg) no-repeat 100% 100%;background-size:contain}.container main .textarea.lock .CodeMirror:before{content:"";position:absolute;width:50%;height:62%;right:5px;bottom:5px;opacity:.06;background:url(lock.623ff62a.svg) no-repeat 100% 100%;background-size:contain}.container main .textarea.home .CodeMirror:before{content:"";position:absolute;width:50%;height:62%;right:5px;bottom:5px;opacity:.06;background:url(home.3a7af05d.svg) no-repeat 100% 100%;background-size:contain}.container main .textarea.home .operation{display:block}.container main .textarea.home .operation .refresh{display:inline-block}.container main .textarea.net .operation{display:block}.container main .textarea.net .operation .net{display:inline-block}.container main .textarea.save .operation{display:block}.container main .textarea.save .operation .save{display:inline-block}.container main .textarea .operation{display:none;position:absolute;z-index:110;top:17px;right:22px;background-color:hsla(0,0%,74.1%,.226);height:20px;padding:2px 13px;border-radius:16px;transition:all .2s}.container main .textarea .operation .refresh{display:none;width:17px;height:20px;opacity:.2;margin:0 3px;background:url(refresh.0b748f9a.svg) no-repeat 50%;background-size:contain}.container main .textarea .operation .refresh:hover{cursor:pointer;opacity:.6}.container main .textarea .operation .net{display:none;width:17px;height:20px;opacity:.2;margin:0 3px;background:url(download.779c3df5.svg) no-repeat 50%;background-size:contain}.container main .textarea .operation .net:hover{cursor:pointer;opacity:.6}.container main .textarea .operation .save{display:none;width:17px;height:20px;opacity:.2;margin:0 3px;background:url(save.8ed52c9e.svg) no-repeat 50%;background-size:contain}.container main .textarea .operation .save:hover{cursor:pointer;opacity:.6}.dialog-item{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:360px;background-color:#fff;border:1px solid #ccc;border-radius:3px;box-shadow:0 2px 4px rgba(0,0,0,.15);display:none;z-index:100}.dialog-item.active{display:block}.dialog-item .item-hader{height:40px;line-height:40px;padding-left:15px;border-bottom:1px solid #e8e8e8;font-size:15px}.dialog-item .item-operation{overflow:hidden;padding:10px;border-top:1px solid #e8e8e8}.dialog-item .item-operation .ui-button{float:right}.dialog-item .item-operation .ui-button+.ui-button{margin-right:10px}.dialog-item .item-body{padding:20px 40px;font-size:14px}.dialog-item .item-body .form-item+.form-item{margin-top:15px}.dialog-item .item-body input{width:200px;font-size:13px}.shade{display:none;position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.3);z-index:99}.context-menu{position:absolute;width:111px;padding:5px 0;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.25);border:1px solid #d0d0d5;border-radius:2px;font-size:14px;animation:fadeIn .2s;z-index:200;left:-99999px;top:-99999px}.context-menu .menu-item{display:block;line-height:20px;padding:8px 10px 7px;color:#4c5161;text-decoration:none;cursor:pointer;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.context-menu .menu-item:hover{background-color:#f0f7ff}.context-menu .menu-item.disabled{cursor:default;pointer-events:none;opacity:.4}.context-menu .menu-item.disabled:hover{background-color:transparent}.context-menu .menu-item .icon{display:inline-block;width:13px;height:13px;transform:translateY(2px)}.context-menu .menu-item .icon img{width:100%;height:100%}.context-menu .menu-line{border:0;border-bottom:1px solid #d0d0d5;margin:7px 11px;opacity:.4}.context-menu .menu-target{cursor:default;padding-top:2px;padding-bottom:6px;font-size:12px;color:hsla(0,0%,72.5%,.6901960784313725);height:12px;line-height:12px;transform:scale(.8)}.CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.CodeMirror-lines{padding:4px 0}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{padding:0 4px}.CodeMirror-gutter-filler,.CodeMirror-scrollbar-filler{background-color:#fff}.CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.CodeMirror-guttermarker{color:#000}.CodeMirror-guttermarker-subtle{color:#999}.CodeMirror-cursor{border-left:1px solid #000;border-right:none;width:0}.CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.cm-fat-cursor div.CodeMirror-cursors{z-index:1}.cm-fat-cursor-mark{background-color:rgba(20,255,20,.5)}.cm-animate-fat-cursor,.cm-fat-cursor-mark{-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}.cm-animate-fat-cursor{width:auto;border:0;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.cm-tab{display:inline-block;text-decoration:inherit}.CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.cm-s-default .cm-header{color:#00f}.cm-s-default .cm-quote{color:#090}.cm-negative{color:#d44}.cm-positive{color:#292}.cm-header,.cm-strong{font-weight:700}.cm-em{font-style:italic}.cm-link{text-decoration:underline}.cm-strikethrough{text-decoration:line-through}.cm-s-default .cm-keyword{color:#708}.cm-s-default .cm-atom{color:#219}.cm-s-default .cm-number{color:#164}.cm-s-default .cm-def{color:#00f}.cm-s-default .cm-variable-2{color:#05a}.cm-s-default .cm-type,.cm-s-default .cm-variable-3{color:#085}.cm-s-default .cm-comment{color:#a50}.cm-s-default .cm-string{color:#a11}.cm-s-default .cm-string-2{color:#f50}.cm-s-default .cm-meta,.cm-s-default .cm-qualifier{color:#555}.cm-s-default .cm-builtin{color:#30a}.cm-s-default .cm-bracket{color:#997}.cm-s-default .cm-tag{color:#170}.cm-s-default .cm-attribute{color:#00c}.cm-s-default .cm-hr{color:#999}.cm-s-default .cm-link{color:#00c}.cm-invalidchar,.cm-s-default .cm-error{color:red}.CodeMirror-composing{border-bottom:2px solid}div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.CodeMirror-activeline-background{background:#e8f2ff}.CodeMirror{position:relative;overflow:hidden;background:#fff}.CodeMirror-scroll{overflow:scroll!important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:none;position:relative}.CodeMirror-sizer{position:relative;border-right:50px solid transparent}.CodeMirror-gutter-filler,.CodeMirror-hscrollbar,.CodeMirror-scrollbar-filler,.CodeMirror-vscrollbar{position:absolute;z-index:6;display:none;outline:none}.CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.CodeMirror-scrollbar-filler{right:0;bottom:0}.CodeMirror-gutter-filler{left:0;bottom:0}.CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none!important;border:none!important}.CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.CodeMirror-gutter-wrapper ::selection{background-color:transparent}.CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.CodeMirror-lines{cursor:text;min-height:1px}.CodeMirror pre.CodeMirror-line,.CodeMirror pre.CodeMirror-line-like{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.CodeMirror-wrap pre.CodeMirror-line,.CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.CodeMirror-rtl pre{direction:rtl}.CodeMirror-code{outline:none}.CodeMirror-gutter,.CodeMirror-gutters,.CodeMirror-linenumber,.CodeMirror-scroll,.CodeMirror-sizer{-moz-box-sizing:content-box;box-sizing:content-box}.CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.CodeMirror-cursor{position:absolute;pointer-events:none}.CodeMirror-measure pre{position:static}div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.CodeMirror-focused div.CodeMirror-cursors,div.CodeMirror-dragcursors{visibility:visible}.CodeMirror-selected{background:#d9d9d9}.CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.CodeMirror-crosshair{cursor:crosshair}.CodeMirror-line::selection,.CodeMirror-line>span::selection,.CodeMirror-line>span>span::selection{background:#d7d4f0}.CodeMirror-line::-moz-selection,.CodeMirror-line>span::-moz-selection,.CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.cm-searching{background-color:#ffa;background-color:rgba(255,255,0,.4)}.cm-force-border{padding-right:.1px}@media print{.CodeMirror div.CodeMirror-cursors{visibility:hidden}}.cm-tab-wrap-hack:after{content:""}span.CodeMirror-selectedtext{background:none}.cm-s-hosts.CodeMirror{background-color:#fff;color:#2e383c;line-height:1.4375}.cm-s-hosts .cm-comment{color:#75787b}.cm-s-hosts .cm-keyword,.cm-s-hosts .cm-property{color:#1d75b3}.cm-s-hosts .cm-atom,.cm-s-hosts .cm-number{color:rgba(29,57,196,.7686274509803922)}.cm-s-hosts .cm-node,.cm-s-hosts .cm-tag{color:#9c3328}.cm-s-hosts .cm-string{color:#b35e14}.cm-s-hosts .cm-qualifier,.cm-s-hosts .cm-variable{color:rgba(4,125,101,.8274509803921568)}.cm-s-hosts pre{padding:0}.cm-s-hosts .CodeMirror-gutters{border:none;border-right:10px solid transparent;background-color:transparent}.cm-s-hosts .CodeMirror-linenumber{padding:0;color:#e0e2e5}.cm-s-hosts .CodeMirror-guttermarker{color:#1d75b3}.cm-s-hosts .CodeMirror-guttermarker-subtle{color:#e0e2e5}.cm-s-hosts .CodeMirror-cursor{width:1px;border:0;background:rgba(155,157,162,.6);z-index:1}.cm-s-hosts .CodeMirror-activeline-background{background:rgba(232,242,255,.5)}.cm-s-hosts div.CodeMirror-selected{background:rgba(232,242,255,.8)}.CodeMirror-simplescroll-horizontal div,.CodeMirror-simplescroll-vertical div{position:absolute;background:#ccc;-moz-box-sizing:border-box;box-sizing:border-box;border:1px solid #bbb;border-radius:2px}.CodeMirror-simplescroll-horizontal,.CodeMirror-simplescroll-vertical{position:absolute;z-index:6;background:#eee}.CodeMirror-simplescroll-horizontal{bottom:0;left:0;height:8px}.CodeMirror-simplescroll-horizontal div{bottom:0;height:100%}.CodeMirror-simplescroll-vertical{right:0;top:0;width:8px}.CodeMirror-simplescroll-vertical div{right:0;width:100%}.CodeMirror-overlayscroll .CodeMirror-gutter-filler,.CodeMirror-overlayscroll .CodeMirror-scrollbar-filler{display:none}.CodeMirror-overlayscroll-horizontal div,.CodeMirror-overlayscroll-vertical div{position:absolute;background:#bcd;border-radius:3px}.CodeMirror-overlayscroll-horizontal,.CodeMirror-overlayscroll-vertical{position:absolute;z-index:6}.CodeMirror-overlayscroll-horizontal{bottom:0;left:0;height:6px}.CodeMirror-overlayscroll-horizontal div{bottom:0;height:100%}.CodeMirror-overlayscroll-vertical{right:0;top:0;width:6px}.CodeMirror-overlayscroll-vertical div{right:0;width:100%}.CodeMirror-dialog{position:absolute;left:0;right:0;background:inherit;z-index:15;padding:.1em .8em;overflow:hidden;color:inherit}.CodeMirror-dialog-top{border-bottom:1px solid #eee;top:0}.CodeMirror-dialog-bottom{border-top:1px solid #eee;bottom:0}.CodeMirror-dialog input{border:none;outline:none;background:transparent;width:20em;color:inherit;font-family:monospace}.CodeMirror-dialog button{font-size:70%} -------------------------------------------------------------------------------- /web/record.56e10638.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/recordFind.08a261bc.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/refresh.0b748f9a.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/save.8ed52c9e.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/subtraction.600c820b.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/unlock.6ef52b3f.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | .cache 4 | dist 5 | package-lock.json -------------------------------------------------------------------------------- /web_source/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 200, 3 | "tabWidth": 2, 4 | "semi": true, 5 | "useTabs": false, 6 | "singleQuote": true, 7 | "bracketSpacing": true 8 | } -------------------------------------------------------------------------------- /web_source/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hosts-switch", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "main.js", 6 | "dependencies": { 7 | "@types/codemirror": "0.0.102", 8 | "aardio": "^2.6.0", 9 | "codemirror": "^5.58.3", 10 | "lu2": "^2020.11.23", 11 | "normalize.css": "^8.0.1" 12 | }, 13 | "devDependencies": { 14 | "@types/node": "^14.14.13", 15 | "less": "^3.13.0", 16 | "parcel-bundler": "^1.12.4", 17 | "parcel-plugin-clean-dist": "0.0.6", 18 | "typescript": "^4.1.3" 19 | }, 20 | "scripts": { 21 | "dev": "parcel src/index.html --port 6060", 22 | "build": "parcel build src/index.html --no-source-maps -d ../web --out-file index.aardio --public-url /web/" 23 | }, 24 | "keywords": [], 25 | "author": "LnnCoCo", 26 | "license": "ISC" 27 | } 28 | -------------------------------------------------------------------------------- /web_source/src/asset/addition.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/download.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/edit.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lnncoco/hosts-switch/bc6dfc271831091629d6bc30f4e2b651a6409157/web_source/src/asset/favicon.png -------------------------------------------------------------------------------- /web_source/src/asset/flag.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/home.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/interpretation.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/link.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/lock.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/menu.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/record.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/recordFind.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/refresh.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/save.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/subtraction.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/asset/unlock.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web_source/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | HostsSwitch 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | 24 |
25 |
26 |
27 |
28 |
29 |
30 |
修改配置
31 |
32 |
标签名称:
33 |
远程地址:
34 |
35 |
36 | 37 | 38 |
39 |
40 | 41 | 42 | 50 | 51 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /web_source/src/js/CodeMirror/hosts.css: -------------------------------------------------------------------------------- 1 | /* hosts theme for codemirror */ 2 | 3 | /* Color scheme */ 4 | 5 | .cm-s-hosts.CodeMirror { 6 | background-color: #ffffff; 7 | color: #2e383c; 8 | line-height: 1.4375; 9 | } 10 | .cm-s-hosts .cm-comment { 11 | color: #75787b; 12 | } 13 | .cm-s-hosts .cm-keyword, 14 | .cm-s-hosts .cm-property { 15 | color: #1d75b3; 16 | } 17 | .cm-s-hosts .cm-atom, 18 | .cm-s-hosts .cm-number { 19 | color: #1d39c4c4; 20 | } 21 | .cm-s-hosts .cm-node, 22 | .cm-s-hosts .cm-tag { 23 | color: #9c3328; 24 | } 25 | .cm-s-hosts .cm-string { 26 | color: #b35e14; 27 | } 28 | .cm-s-hosts .cm-variable, 29 | .cm-s-hosts .cm-qualifier { 30 | color: #047d65d3; 31 | } 32 | 33 | /* Editor styling */ 34 | 35 | .cm-s-hosts pre { 36 | padding: 0; 37 | } 38 | 39 | .cm-s-hosts .CodeMirror-gutters { 40 | border: none; 41 | border-right: 10px solid transparent; 42 | background-color: transparent; 43 | } 44 | 45 | .cm-s-hosts .CodeMirror-linenumber { 46 | padding: 0; 47 | color: #e0e2e5; 48 | } 49 | 50 | .cm-s-hosts .CodeMirror-guttermarker { 51 | color: #1d75b3; 52 | } 53 | .cm-s-hosts .CodeMirror-guttermarker-subtle { 54 | color: #e0e2e5; 55 | } 56 | 57 | .cm-s-hosts .CodeMirror-cursor { 58 | width: 1px; 59 | border: 0; 60 | background: rgba(155, 157, 162, 0.6); 61 | z-index: 1; 62 | } 63 | 64 | .cm-s-hosts .CodeMirror-activeline-background { 65 | background: rgb(232, 242, 255, 0.5); 66 | } 67 | .cm-s-hosts div.CodeMirror-selected { 68 | background: rgb(232, 242, 255, 0.8); 69 | } 70 | -------------------------------------------------------------------------------- /web_source/src/js/CodeMirror/index.ts: -------------------------------------------------------------------------------- 1 | import * as CodeMirror from 'codemirror/lib/codemirror'; 2 | import 'codemirror/lib/codemirror.css'; 3 | // 语法逻辑 4 | import './modeHosts'; 5 | // 主题样式 6 | import './hosts.css'; 7 | // 高亮当前行 8 | import 'codemirror/addon/selection/active-line'; 9 | // 滚动条 10 | import 'codemirror/addon/scroll/simplescrollbars'; 11 | import 'codemirror/addon/scroll/simplescrollbars.css'; 12 | // 搜索 13 | import 'codemirror/addon/dialog/dialog'; 14 | import 'codemirror/addon/dialog/dialog.css'; 15 | import 'codemirror/addon/scroll/annotatescrollbar'; 16 | import 'codemirror/addon/search/matchesonscrollbar'; 17 | import 'codemirror/addon/search/jump-to-line'; 18 | import 'codemirror/addon/search/search'; 19 | import 'codemirror/addon/search/searchcursor'; 20 | // 相关事件 21 | import { changeTextareaTip, eventTextareaSave } from '../textarea'; 22 | 23 | let target = null; 24 | let CodeMirrorEditor = null; 25 | const options = { 26 | mode: 'hosts', 27 | theme: 'hosts', 28 | tabSize: 2, 29 | readOnly: false, // 只读模式 30 | lineNumbers: true, //显示行号 31 | styleActiveLine: true, // 高亮当前行 32 | lineWrapping: true, // 换行 33 | scrollbarStyle: 'overlay', // 滚动条样式 34 | extraKeys: { 35 | 'Ctrl-S': eventTextareaSave, 36 | }, 37 | }; 38 | 39 | /** 40 | * 初始化文本编辑器 41 | * @param {boolean} readOnly 是否只读 42 | */ 43 | function init(readOnly: boolean = false) { 44 | options.readOnly = readOnly; 45 | target = document.getElementById('textarea'); 46 | CodeMirrorEditor = CodeMirror.fromTextArea(target, options); 47 | CodeMirrorEditor.setSize('100%', '100%'); 48 | CodeMirrorEditor.on('change', changeTextareaTip); 49 | } 50 | 51 | /** 52 | * 设置编辑器数据 53 | * @param {string} text 文本内容 54 | * @param {boolean} readOnly 是否只读 55 | */ 56 | function setValue(text: string, readOnly: boolean = false) { 57 | CodeMirrorEditor.setValue(text); 58 | if (typeof readOnly === 'boolean') CodeMirrorEditor.setOption('readOnly', readOnly); 59 | } 60 | 61 | /** 62 | * 获取编辑器中文本数据 63 | */ 64 | function getValue(): string { 65 | return CodeMirrorEditor.getValue(); 66 | } 67 | 68 | /** 69 | * 设置当前项为只读 70 | * @param {boolean} readOnly 是否只读 71 | */ 72 | function setReadOnly(readOnly: boolean) { 73 | return CodeMirrorEditor.setOption('readOnly', readOnly); 74 | } 75 | 76 | export default { 77 | target: CodeMirrorEditor, 78 | init, 79 | setValue, 80 | getValue, 81 | setReadOnly, 82 | }; 83 | -------------------------------------------------------------------------------- /web_source/src/js/CodeMirror/modeHosts.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | (function (mod) { 5 | if (typeof exports == 'object' && typeof module == 'object') 6 | // CommonJS 7 | mod(require('codemirror/lib/codemirror')); 8 | else if (typeof define == 'function' && define.amd) 9 | // AMD 10 | define(['codemirror/lib/codemirror'], mod); 11 | // Plain browser env 12 | else mod(CodeMirror); 13 | })(function (CodeMirror) { 14 | 'use strict'; 15 | 16 | CodeMirror.defineMode('hosts', function (config, parserConfig) { 17 | var indentUnit = config.indentUnit; 18 | var curPunc; 19 | 20 | function tokenBase(stream, state) { 21 | var ch = stream.next(); 22 | if (ch == '#') { 23 | stream.skipToEnd(); 24 | return 'comment'; 25 | } 26 | 27 | if (/\d/.test(ch)) { 28 | stream.eatWhile(/[\w\.]/); 29 | return 'number'; 30 | } 31 | 32 | stream.eatWhile(/[\w\$_]/); 33 | return 'variable'; 34 | } 35 | 36 | function Context(indented, column, type, align, prev) { 37 | this.indented = indented; 38 | this.column = column; 39 | this.type = type; 40 | this.align = align; 41 | this.prev = prev; 42 | } 43 | 44 | //Interface 45 | return { 46 | startState: function (basecolumn) { 47 | return { 48 | tokenize: null, 49 | context: new Context((basecolumn || 0) - indentUnit, 0, 'top', false), 50 | indented: 0, 51 | startOfLine: true, 52 | }; 53 | }, 54 | 55 | token: function (stream, state) { 56 | var ctx = state.context; 57 | if (stream.sol()) { 58 | if (ctx.align == null) ctx.align = false; 59 | state.indented = stream.indentation(); 60 | state.startOfLine = true; 61 | } 62 | if (stream.eatSpace()) return null; 63 | curPunc = null; 64 | var style = (state.tokenize || tokenBase)(stream, state); 65 | if (style == 'comment') return style; 66 | if (ctx.align == null) ctx.align = true; 67 | 68 | if (curPunc == ctx.type) { 69 | state.context = state.context.prev; 70 | } 71 | state.startOfLine = false; 72 | return style; 73 | }, 74 | 75 | electricChars: '{}', 76 | lineComment: '#', 77 | fold: 'brace', 78 | }; 79 | }); 80 | 81 | CodeMirror.defineMIME('hosts', { 82 | name: 'hosts', 83 | multiLineStrings: true, 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /web_source/src/js/bus.ts: -------------------------------------------------------------------------------- 1 | interface IBus { 2 | [key: string]: any; 3 | } 4 | const bus: IBus = {}; 5 | 6 | export default bus; 7 | -------------------------------------------------------------------------------- /web_source/src/js/contextMenu.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | import BUS from './bus'; 4 | import template from '~/lib/template'; 5 | import dataAction from './dataAction'; 6 | import CodeMirror from './CodeMirror'; 7 | import { modifyTextareaLockState } from './textarea'; 8 | import { refreshDnsCache } from './util'; 9 | import { openDialog, setDialog, closeDialog, dialogApply } from './dialog'; 10 | import iconModify from '~/asset/edit.svg'; 11 | import iconRefresh from '~/asset/refresh.svg'; 12 | import iconDownload from '~/asset/download.svg'; 13 | import iconRemove from '~/asset/subtraction.svg'; 14 | import iconAddition from '~/asset/addition.svg'; 15 | import iconLock from '~/asset/lock.svg'; 16 | import iconUnlock from '~/asset/unlock.svg'; 17 | 18 | const contextMenu = { 19 | li: function (itemData: DATA.item) { 20 | const lock = { line: false, text: '锁定此项', icon: iconLock, action: 'lock' }; 21 | const unlock = { line: false, text: '解锁此项', icon: iconUnlock, action: 'unlock' }; 22 | const list = [ 23 | { line: false, text: '修改参数', icon: iconModify, action: 'modify' }, 24 | { line: false, text: '更新数据', icon: iconDownload, action: 'update' }, 25 | { line: true }, 26 | { line: false, text: '添加新项', icon: iconAddition, action: 'add' }, 27 | { line: false, text: '删除此项', icon: iconRemove, action: 'remove' }, 28 | ]; 29 | 30 | // 固定插入在第一层次的最后 31 | let index = 0; 32 | for (const item of list) { 33 | if (item.line) { 34 | if (itemData.lock) list.splice(index, 0, unlock); 35 | else list.splice(index, 0, lock); 36 | break; 37 | } 38 | index++; 39 | } 40 | 41 | return list; 42 | }, 43 | nav: function () { 44 | return [ 45 | { line: false, text: '添加新项', icon: iconAddition, action: 'add' }, 46 | { line: false, text: '全部更新', icon: iconDownload, action: 'updateAll' }, 47 | { line: false, text: '刷新缓存', icon: iconRefresh, action: 'refresh' }, 48 | ]; 49 | }, 50 | }; 51 | 52 | const actionFn = { 53 | lock: function () { 54 | dataAction.modify(BUS.mouseTargetId, { lock: true }, () => { 55 | const activeData = dataAction.getActionItemInfo(); 56 | if (activeData.id.toString() === BUS.mouseTargetId.toString()) { 57 | modifyTextareaLockState(true); 58 | CodeMirror.setReadOnly(true); 59 | } 60 | }); 61 | }, 62 | unlock: function () { 63 | dataAction.modify(BUS.mouseTargetId, { lock: false }, () => { 64 | const activeData = dataAction.getActionItemInfo(); 65 | if (activeData.id.toString() === BUS.mouseTargetId.toString()) { 66 | modifyTextareaLockState(false); 67 | CodeMirror.setReadOnly(false); 68 | } 69 | }); 70 | }, 71 | modify: function () { 72 | const activeData = dataAction.getItemInfo(BUS.mouseTargetId); 73 | setDialog(activeData.name, activeData.url); 74 | openDialog(); 75 | }, 76 | add: function () { 77 | dataAction.add().active('-1').render(); // active到最新项 78 | }, 79 | remove: function () { 80 | dataAction.remove(BUS.mouseTargetId).render(); 81 | BUS.mouseTargetId = null; // 清除当前id指向 82 | }, 83 | update: function () { 84 | dataAction.asyncUpdateHosts(BUS.mouseTargetId); 85 | }, 86 | updateAll: function () { 87 | dataAction.asyncUpdateAllHosts(); 88 | }, 89 | refresh: function () { 90 | refreshDnsCache(); 91 | }, 92 | }; 93 | 94 | /** 95 | * 初始化操作 96 | */ 97 | function init() { 98 | window.oncontextmenu = function (event: MouseEvent) { 99 | event.preventDefault(); 100 | show(event); 101 | return false; 102 | }; 103 | // 单击dialog 取消按钮 104 | document.querySelector('#dialog_cancel').addEventListener('click', closeDialog, false); 105 | // 单击dialog 确定按钮 106 | document.querySelector('#dialog_apply').addEventListener('click', dialogApply, false); 107 | 108 | document.addEventListener('click', close); 109 | BUS.contextMenu.addEventListener('click', function (e) { 110 | for (const item of e.path) { 111 | if (item.tagName === 'LI') { 112 | const action = item.dataset.action; 113 | if (actionFn[action]) actionFn[action](); 114 | break; 115 | } 116 | } 117 | }); 118 | } 119 | 120 | /** 121 | * 当前鼠标右键激活项增删指示状态 122 | * @param {boolean} status 123 | * @param {HTMLElement} target 要处理的DOM对象 124 | */ 125 | function curMouseItemStatus(status: boolean, target?: HTMLElement) { 126 | if (status) return target.classList.add('mouse'); 127 | document.querySelector('#nav ul .mouse')?.classList.remove('mouse'); 128 | } 129 | 130 | /** 131 | * 判断是否是菜单项 132 | * @param {MouseEvent} event 133 | */ 134 | function isNavItem(event: MouseEvent) { 135 | return (event as any).path.some((element) => { 136 | curMouseItemStatus(false); 137 | if (element.tagName === 'LI') { 138 | // 处理类名判断是否是菜单项 139 | const className = element.className; 140 | if (className && className.split(' ').includes('nav-item')) { 141 | curMouseItemStatus(true, element); // 当前右键激活项添加类名 142 | BUS.mouseTargetId = element.dataset.id; // 存储当前节点的id 143 | const itemData = dataAction.getItemInfo(BUS.mouseTargetId); // 获取当前项的数据 144 | BUS.contextMenu.innerHTML = template('template_contextMenu', { target: itemData.name, list: contextMenu.li(itemData), isLocal: !itemData.url, isHome: itemData.home }); // 渲染li右键菜单 145 | return true; 146 | } 147 | } else if (element.tagName === 'NAV') { 148 | BUS.contextMenu.innerHTML = template('template_contextMenu', { list: contextMenu.nav() }); // 渲染nav右键菜单 149 | return true; 150 | } 151 | return false; 152 | }); 153 | } 154 | 155 | /** 156 | * 显示右键菜单 157 | * @param {MouseEvent} event 158 | */ 159 | function show(event: MouseEvent) { 160 | if (!isNavItem(event)) return; 161 | // 获取当前鼠标位置 162 | let mouseX = event.clientX; 163 | let mouseY = event.clientY; 164 | // 判断边界值,防止菜单栏溢出可视窗口 165 | const winHeight = document.documentElement.clientHeight ?? document.body.clientHeight; 166 | if (mouseY > winHeight - BUS.contextMenu.offsetHeight) mouseY = winHeight - BUS.contextMenu.offsetHeight - 10; 167 | else mouseY = mouseY; 168 | 169 | BUS.contextMenu.style.left = `${mouseX}px`; 170 | BUS.contextMenu.style.top = `${mouseY}px`; 171 | } 172 | 173 | /** 174 | * 关闭右键菜单 175 | */ 176 | function close() { 177 | // 使用 display: none 会导致offsetHeight获取高度为0的情况 178 | BUS.contextMenu.style.left = '-99999px'; 179 | BUS.contextMenu.style.top = '-99999px'; 180 | BUS.mouseTarget = null; 181 | curMouseItemStatus(false); 182 | } 183 | 184 | export default { init, show, close }; 185 | -------------------------------------------------------------------------------- /web_source/src/js/dataAction/DATA.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace DATA { 2 | export interface item { 3 | home?: boolean; // 本地使用Hosts项标识 4 | id: number; // 项唯一id 5 | name: string; // 项名称 6 | active: boolean; // 是否激活显示 7 | checked: boolean; // 是否开启 8 | lock: boolean; // 是否只读 默认false 9 | url: string; // url 10 | status: boolean; // 当网络获取报错时,此项为false 11 | hosts: string; // HOSTS文本内容 12 | } 13 | export type list = item[]; 14 | } 15 | -------------------------------------------------------------------------------- /web_source/src/js/dataAction/DATA.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import CodeMirror from '../CodeMirror'; 3 | import { saveSystemHosts, saveConfigData } from '../util'; 4 | 5 | // 存放host渲染数据 6 | let DATA: DATA.list = []; 7 | 8 | /** 9 | * 获取DATA数据 10 | */ 11 | export function iniData(data: DATA.list) { 12 | DATA = JSON.parse(JSON.stringify(data)); 13 | return true; 14 | } 15 | 16 | /** 17 | * 获取DATA数据 18 | */ 19 | export function getData() { 20 | return DATA; 21 | } 22 | 23 | /** 24 | * 获取当前激活项的所有信息 25 | */ 26 | export function getActionItemInfo() { 27 | for (const item of DATA) { 28 | if (item.active) return item; 29 | } 30 | DATA[0].active = true; // 如果没有激活项就默认激活第一个 31 | return DATA[0]; 32 | } 33 | 34 | /** 35 | * 获取指定项的所有信息 36 | * @param {string} id 37 | */ 38 | export function getItemInfo(id: string) { 39 | for (const item of DATA) { 40 | if (item.id.toString() === id.toString()) return item; 41 | } 42 | } 43 | 44 | /** 45 | * 获取指定项的Hosts信息 46 | * @param {string} id 47 | */ 48 | export function getItemHosts(id: string) { 49 | for (const item of DATA) { 50 | if (item.id.toString() === id.toString()) return item.hosts; 51 | } 52 | } 53 | 54 | /** 55 | * 获取本地使用项(home项) 56 | */ 57 | export function getUseItemInfo() { 58 | const use = DATA[0]; 59 | if (use.home) return use; 60 | for (const item of DATA) { 61 | if (item.home) return item; 62 | } 63 | return false; 64 | } 65 | 66 | /** 67 | * 添加新的项 68 | * @param {string} name 69 | * @param {function} fn 70 | */ 71 | export function add(name?: string, fn?: (list: DATA.list) => any) { 72 | DATA.push({ 73 | id: DATA[DATA.length - 1].id + 1, 74 | name: name ? name : `新增项${DATA.length + 1}`, 75 | active: false, 76 | checked: false, 77 | lock: false, 78 | url: '', 79 | status: true, 80 | hosts: '', 81 | }); 82 | fn?.(DATA); 83 | return true; 84 | } 85 | 86 | /** 87 | * 删除指定项参数 88 | * @param {string} id 89 | * @param {function} fn 90 | */ 91 | export function remove(id: string, fn?: (list: DATA.list, home: DATA.item) => any) { 92 | let curIndex = -1; 93 | DATA.forEach((item, index) => { 94 | if (item.id.toString() === id.toString()) { 95 | curIndex = index; 96 | } 97 | }); 98 | if (curIndex >= 0) { 99 | DATA.splice(curIndex, 1); 100 | updateUseHosts(fn); 101 | return true; 102 | } 103 | return false; 104 | } 105 | 106 | /** 107 | * 修改指定项参数 108 | * @param {string} id 109 | * @param {Object} params 110 | */ 111 | function modify(id: string, params: { name?: string; url?: string; lock?: boolean }) { 112 | for (const item of DATA) { 113 | if (item.id.toString() === id.toString()) { 114 | if (params.name) item.name = params.name; 115 | if (params.url) item.url = params.url; 116 | if (typeof params.lock === 'boolean') { 117 | item.lock = params.lock; 118 | } 119 | break; 120 | } 121 | } 122 | return true; 123 | } 124 | 125 | /** 126 | * 修改多项的多项参数 127 | * @param {function} isFn 判断是否执行的函数 128 | * @param {function} modifyFn 需要执行的函数 129 | * @param {function} finalFn 完成后执行的函数 130 | */ 131 | function modifyEvery(isFn: (curItem: DATA.item) => boolean, modifyFn: (item: DATA.item, index: number) => void, finalFn?: () => void) { 132 | if (isFn) { 133 | let index = 0; 134 | for (const item of DATA) { 135 | if (isFn(item)) modifyFn?.(item, index); 136 | index++; 137 | } 138 | finalFn?.(); 139 | return true; 140 | } 141 | return false; 142 | } 143 | 144 | /** 145 | * 当前项状态激活(其他项切换为关闭) 146 | * @param {string} id 147 | * @param {function} fn 148 | */ 149 | export function active(id: string, fn?: (list: DATA.list, home: DATA.item) => any) { 150 | let curItem: false | DATA.item = false; 151 | let curId = id.toString(); 152 | if (id === '-1') curId = (DATA.length - 1).toString(); // 激活最后一项 153 | DATA.forEach((item) => { 154 | if (item.active) item.hosts = CodeMirror.getValue(); 155 | // 只能一个激活 156 | if (item.id.toString() === curId) { 157 | item.active = true; 158 | curItem = item; 159 | } else item.active = false; 160 | }); 161 | return updateUseHosts(fn); 162 | } 163 | 164 | /** 165 | * 当前项Switch状态切换 166 | * @param {string} id 167 | * @param {boolean} status 168 | * @param {function} fn 169 | */ 170 | export function checked(id: string, status: boolean, fn?: (list: DATA.list, home: DATA.item) => any) { 171 | DATA.forEach((item) => { 172 | // 能够开启多个 多个合并到本地HOSTS 173 | if (item.id.toString() === id.toString()) item.checked = status; 174 | }); 175 | return updateUseHosts(fn); 176 | } 177 | 178 | /** 179 | * 更新使用中Hosts数据(合并switch项为true的数据) 180 | * active checked add remove 调用 181 | * @param {function} fn 182 | */ 183 | export function updateUseHosts(fn?: (list: DATA.list, home: DATA.item) => any) { 184 | const use = getUseItemInfo(); 185 | if (!use) return false; 186 | let hosts = ''; 187 | for (const item of DATA) { 188 | if (item.checked && item.status && !item.home) { 189 | if (hosts) hosts += '\r\n\r\n'; 190 | hosts += item.hosts; 191 | } 192 | } 193 | use.hosts = hosts; 194 | saveSystemHosts(use.hosts); // 应用到系统 195 | saveConfigData(DATA); // System Hosts项变了 每次更新保存整体数据 196 | if (fn) return fn(DATA, use); 197 | return true; 198 | } 199 | 200 | export default { 201 | iniData, 202 | add, 203 | remove, 204 | // 改 205 | modify, 206 | modifyEvery, 207 | active, 208 | checked, 209 | updateUseHosts, 210 | // 查 211 | getData, 212 | getItemInfo, 213 | getActionItemInfo, 214 | getItemHosts, 215 | getUseItemInfo, 216 | }; 217 | -------------------------------------------------------------------------------- /web_source/src/js/dataAction/defaultConfig.ts: -------------------------------------------------------------------------------- 1 | export default [ 2 | { 3 | home: true, // 本地使用Hosts项标识 4 | id: 0, 5 | name: 'System Hosts', 6 | active: true, 7 | checked: true, 8 | lock: true, // 只能自定义新项修改 保存后自动混合入系统Hosts 9 | url: '', 10 | status: true, 11 | hosts: '', 12 | }, 13 | { 14 | id: 1, 15 | name: 'Local Hosts', 16 | active: false, 17 | checked: true, 18 | lock: false, 19 | url: '', 20 | status: true, 21 | hosts: '', 22 | }, 23 | { 24 | id: 2, 25 | name: 'Github Hosts', 26 | active: false, 27 | checked: false, 28 | lock: false, 29 | url: 'https://gitee.com/xueweihan/codes/6g793pm2k1hacwfbyesl464/raw?blob_name=GitHub520.yml', 30 | status: true, 31 | hosts: '', 32 | }, 33 | { 34 | id: 3, 35 | name: 'Google Hosts', 36 | active: false, 37 | checked: false, 38 | lock: false, 39 | url: 'https://raw.githubusercontent.com/googlehosts/hosts/master/hosts-files/hosts', 40 | status: true, 41 | hosts: '', 42 | }, 43 | ]; 44 | -------------------------------------------------------------------------------- /web_source/src/js/dataAction/index.ts: -------------------------------------------------------------------------------- 1 | import { getSystemHosts, requestHosts, backupLocalHosts, getConfigData, saveConfigData, tipSuccess, tipWarning, tipError } from '../util'; 2 | import defaultConfig from './defaultConfig'; 3 | // 内部组件 4 | import DATA from './DATA'; 5 | import render, { renderTextareaContent } from './render'; 6 | 7 | /** 8 | * 数据状态统一控制 9 | * get 函数返回需要的数据信息 10 | * async 返回Promise数据 11 | * 除了render init其余为操作项,都返回this 12 | */ 13 | 14 | /** 15 | * 初始化(始终存在默认项本地Hosts) 16 | */ 17 | async function init() { 18 | backupLocalHosts(); // 有备份文件时会自动跳过备份 文件名system.bak 19 | const systemHosts = await getSystemHosts(); 20 | defaultConfig[0].hosts = typeof systemHosts !== 'boolean' ? systemHosts : ''; 21 | defaultConfig[1].hosts = typeof systemHosts !== 'boolean' ? systemHosts : ''; 22 | const config = await getConfigData(); 23 | if (typeof config === 'boolean' && config === false) return; // 如果读取错误不再继续进行 24 | if (!config) saveConfigData(defaultConfig); // 没有main字段时会返回null 25 | DATA.iniData(config || defaultConfig); 26 | } 27 | 28 | export default { 29 | getData: DATA.getData, 30 | 31 | render, 32 | 33 | init: async function () { 34 | await init(); 35 | render(); 36 | }, 37 | 38 | /** 39 | * 添加新的项 40 | * @param {string} name 41 | */ 42 | add: function (name?: string) { 43 | DATA.add(name); 44 | return this; 45 | }, 46 | 47 | /** 48 | * 删除指定项参数 49 | * @param {string} id 50 | */ 51 | remove: function (id: string) { 52 | DATA.remove(id); 53 | return this; 54 | }, 55 | 56 | /** 57 | * 当前项Switch状态切换 58 | * @param {string} id 59 | * @param {boolean} status 60 | */ 61 | checked: function (id: string, status: boolean) { 62 | DATA.checked(id, status); 63 | return this; 64 | }, 65 | 66 | /** 67 | * 当前项状态激活(其他项切换为关闭) 68 | * @param {string} id 69 | */ 70 | active: function (id: string) { 71 | DATA.active(id); 72 | return this; 73 | }, 74 | 75 | /** 76 | * 修改指定项参数 77 | * @param {string} id 78 | * @param {Object} params 79 | * @param {function} fn 回调函数 80 | */ 81 | modify: function (id: string, params: { name?: string; url?: string; lock?: boolean }, fn?: () => any) { 82 | DATA.modify(id, params); 83 | fn?.(); 84 | return this; 85 | }, 86 | 87 | /** 88 | * 更新使用中Hosts数据(合并switch项为true的数据) 89 | * @param {function} fn 90 | */ 91 | updateUseHosts: DATA.updateUseHosts, 92 | 93 | /** 94 | * 获取指定项的所有信息 95 | * @param {string} id 96 | */ 97 | getItemInfo: DATA.getItemInfo, 98 | 99 | /** 100 | * 获取当前激活项的所有信息(如果没激活项则返回第一项) 101 | */ 102 | getActionItemInfo: DATA.getActionItemInfo, 103 | 104 | /** 105 | * 获取指定项的Hosts信息 106 | * @param {string} id 107 | */ 108 | getItemHosts: DATA.getItemHosts, 109 | 110 | /** 111 | * 更新指定id远程Hosts信息 112 | * @param {string} id 113 | */ 114 | asyncUpdateHosts: async function (id: string) { 115 | const curData = DATA.getItemInfo(id); 116 | if (curData.home) { 117 | // 外部修改存到当前数据 118 | const res = await getSystemHosts(); 119 | if (typeof res !== 'boolean') { 120 | if (curData.hosts !== res) { 121 | curData.hosts = res; 122 | render(); 123 | tipSuccess(`请手动保存外部修改,切换后数据将丢失`); 124 | } else tipSuccess(`${curData.name} 刷新成功`); 125 | } else tipError(`${curData.name} 刷新失败`); 126 | return; 127 | } else if (curData.url) { 128 | const res = await requestHosts(curData.url); 129 | if (res.code) { 130 | tipError(`"${curData.name}" 更新错误: ${res.message}`); 131 | curData.status = false; // 获取失败设置false 132 | } else { 133 | curData.hosts = res.html; 134 | curData.status = true; 135 | DATA.updateUseHosts(); 136 | tipSuccess(`"${curData.name}" 更新成功`); 137 | if (curData.active) renderTextareaContent(curData.id.toString()); 138 | } 139 | } 140 | }, 141 | 142 | /** 143 | * 更新所有远程Hosts信息 144 | */ 145 | asyncUpdateAllHosts: async function () { 146 | DATA.modifyEvery( 147 | (item) => !!item.url, // 更新的条件 148 | async (curData, index) => { 149 | const res = await requestHosts(curData.url); 150 | if (res.code) { 151 | setTimeout((e) => { 152 | tipError(`"${curData.name}"更新错误: ${res.message}`); 153 | }, index * 360); 154 | curData.status = false; // 获取失败设置false 155 | } else { 156 | curData.hosts = res.html; 157 | curData.status = true; 158 | tipSuccess(`"${curData.name}"更新成功`); 159 | if (curData.active) renderTextareaContent(curData.id.toString()); 160 | } 161 | }, 162 | DATA.updateUseHosts // 完成后需执行 更新Hosts函数 163 | ); 164 | }, 165 | 166 | /** 167 | * 比较指定id hosts数据与传入数据是否有差异 168 | * @param {string} id 169 | * @param {string} diffText 170 | */ 171 | inconformity: function (id: string, diffText: string) { 172 | const curData = DATA.getItemInfo(id); 173 | if (curData.home) return false; 174 | return !(curData.hosts === diffText); 175 | }, 176 | }; 177 | -------------------------------------------------------------------------------- /web_source/src/js/dataAction/render.ts: -------------------------------------------------------------------------------- 1 | import DATA from './DATA'; 2 | import BUS from '../bus'; 3 | import CodeMirror from '../CodeMirror'; 4 | import template from '~/lib/template'; 5 | import { modifyTextareaLockState, modifyTextareaType, modifyTextareaAttrId } from '../textarea'; 6 | 7 | function inferType(item) { 8 | let curType = 'local'; 9 | if (item.home) curType = 'home'; 10 | if (item.url) curType = 'net'; 11 | return curType; 12 | } 13 | 14 | /** 15 | * 渲染数据 16 | */ 17 | export function render() { 18 | if (process.env.NODE_ENV !== 'production') console.log('render data', DATA.getData()); 19 | 20 | const activeData = DATA.getActionItemInfo(); 21 | // 判断当前项种类 22 | modifyTextareaType(inferType(activeData)); 23 | modifyTextareaLockState(activeData.lock); 24 | modifyTextareaAttrId(activeData.id.toString()); 25 | 26 | const html = template('template_nav', DATA.getData()); 27 | BUS.nav.innerHTML = html; // 将渲染好的html插入到nav中 28 | // 设置nav高度 过长时能显示滚动条 29 | BUS.nav.style.height = `${document.body.clientHeight - 5}px`; 30 | 31 | renderTextareaContent(activeData.id.toString()); 32 | return true; 33 | } 34 | 35 | /** 36 | * 修改文本框内容 37 | * @param {string} id 38 | */ 39 | export async function renderTextareaContent(id: string) { 40 | const itemData = DATA.getItemInfo(id); 41 | CodeMirror.setValue(itemData.hosts, itemData.lock); 42 | } 43 | 44 | export default render; 45 | -------------------------------------------------------------------------------- /web_source/src/js/dialog.ts: -------------------------------------------------------------------------------- 1 | import BUS from './bus'; 2 | import dataAction from './dataAction'; 3 | import { tipSuccess } from './util'; 4 | 5 | /* dialog相关 */ 6 | export function openDialog() { 7 | BUS.dialog.style.display = 'block'; 8 | BUS.shade.style.display = 'block'; 9 | } 10 | 11 | export function closeDialog() { 12 | BUS.dialog.style.display = 'none'; 13 | BUS.shade.style.display = 'none'; 14 | clearDialog(); 15 | } 16 | 17 | export function setDialog(text: string, url?: string) { 18 | (BUS.inputName as HTMLInputElement).value = text ?? ''; 19 | (BUS.inputUrl as HTMLInputElement).value = url ?? ''; 20 | } 21 | export function clearDialog() { 22 | BUS.inputName.removeAttribute('data-id'); 23 | (BUS.inputName as HTMLInputElement).value = ''; 24 | (BUS.inputUrl as HTMLInputElement).value = ''; 25 | } 26 | 27 | export function dialogApply() { 28 | if (BUS.mouseTargetId) { 29 | const name = (BUS.inputName as HTMLInputElement).value; 30 | const url = (BUS.inputUrl as HTMLInputElement).value; 31 | dataAction.modify(BUS.mouseTargetId, { name, url }).render(); 32 | BUS.mouseTargetId = null; 33 | tipSuccess('操作成功'); 34 | closeDialog(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /web_source/src/js/init.ts: -------------------------------------------------------------------------------- 1 | import BUS from './bus'; 2 | import codeMirror from './CodeMirror'; 3 | import dataAction from './dataAction'; 4 | import contextMenu from './contextMenu'; 5 | import { eventTextareaUpdate, eventTextareaSave } from './textarea'; 6 | 7 | export default function init() { 8 | initBusData(); 9 | initBind(); 10 | // 初始化导航栏 11 | dataAction.init(); 12 | // 初始化编辑器 13 | codeMirror.init(); 14 | } 15 | 16 | /* 初始化DOM对象相关数据 */ 17 | function initBusData() { 18 | BUS.nav = document.querySelector('#nav ul'); // 导航栏 19 | BUS.textarea = document.querySelector('.textarea'); // 文本组件框 20 | BUS.dialog = document.querySelector('.dialog-item'); // 弹出窗 21 | BUS.inputName = document.querySelector('.item-body input[name=name]'); // 弹出窗输入框name 22 | BUS.inputUrl = document.querySelector('.item-body input[name=url]'); // 弹出窗输入框url 23 | BUS.shade = document.querySelector('.shade'); // 遮罩层 24 | BUS.contextMenu = document.querySelector('.context-menu'); // 右键菜单 25 | } 26 | 27 | /* 禁用影响使用的快捷键 */ 28 | function disabledKeyboardShortcuts() { 29 | window.onkeydown = window.onkeyup = window.onkeypress = function (event: KeyboardEvent) { 30 | //禁止ctrl+u 31 | if (event.ctrlKey && event.key.toLowerCase() == 'u') return false; 32 | //禁止ctrl+s 33 | if (event.ctrlKey && event.key.toLowerCase() == 's') return false; 34 | //禁止ctrl+shift+i 35 | if (event.ctrlKey && event.shiftKey && event.key.toLowerCase() == 'i') return false; 36 | //禁止 F5 37 | if (event.key == 'F5') return false; 38 | //禁止 F12 39 | if (event.key == 'F12') return false; 40 | }; 41 | } 42 | 43 | /* 初始化绑定 */ 44 | function initBind() { 45 | if (process.env.NODE_ENV === 'production') disabledKeyboardShortcuts(); 46 | // 鼠标右键绑定 47 | contextMenu.init(); 48 | // nav上的 option与switch响应 49 | BUS.nav.addEventListener('click', function (e) { 50 | // 开启关闭切换 51 | if ((e.target as HTMLElement).tagName === 'INPUT') { 52 | const checked = (e.target as HTMLInputElement).checked; 53 | const id = (e as any).path[2].dataset.id; 54 | dataAction.checked(id, checked).render(); 55 | } 56 | // 切换active 57 | if ((e.target as HTMLElement).tagName === 'LI') { 58 | const id = (e.target as HTMLElement).dataset.id; 59 | dataAction.active(id).render(); 60 | } 61 | }); 62 | // 文本框中刷新按钮 63 | document.querySelector('.textarea .operation .refresh').addEventListener('click', eventTextareaUpdate); 64 | // 文本框中更新按钮 65 | document.querySelector('.textarea .operation .net').addEventListener('click', eventTextareaUpdate); 66 | // 文本框中保存按钮 67 | document.querySelector('.textarea .operation .save').addEventListener('click', eventTextareaSave); 68 | } 69 | -------------------------------------------------------------------------------- /web_source/src/js/main.ts: -------------------------------------------------------------------------------- 1 | import 'normalize.css'; 2 | import 'lu2/theme/pure/css/common/ui'; 3 | import '~/styles/index.less'; 4 | import init from './init'; 5 | 6 | if (process.env.NODE_ENV !== 'production') { 7 | console.log('▄▄▌ ▐ ▄ ▐ ▄ ▄▄· ▄▄· '); 8 | console.log('██• •█▌▐█•█▌▐█▐█ ▌▪▪ ▐█ ▌▪▪ '); 9 | console.log('██▪ ▐█▐▐▌▐█▐▐▌██ ▄▄ ▄█▀▄ ██ ▄▄ ▄█▀▄ '); 10 | console.log('▐█▌▐▌██▐█▌██▐█▌▐███▌▐█▌.▐▌▐███▌▐█▌.▐▌'); 11 | console.log('.▀▀▀ ▀▀ █▪▀▀ █▪·▀▀▀ ▀█▄▀▪·▀▀▀ ▀█▄▀▪ ', '调试模式', process.env.NODE_ENV); 12 | } 13 | 14 | window.onload = init; 15 | -------------------------------------------------------------------------------- /web_source/src/js/textarea.ts: -------------------------------------------------------------------------------- 1 | import BUS from './bus'; 2 | import codeMirror from './CodeMirror'; 3 | import dataAction from './dataAction'; 4 | import { tipSuccess, tipError } from './util'; 5 | 6 | /** 7 | * 增删的类名 8 | * @param {string} content 9 | */ 10 | export function modifyTextareaAttrId(content: string) { 11 | return (BUS.textarea.dataset.id = content); 12 | } 13 | 14 | /** 15 | * 增删的类名 16 | * @param {string} className 17 | */ 18 | export function modifyTextareaClass(type: string, className: string) { 19 | if (type === 'add') return BUS.textarea.classList.add(className); 20 | if (type === 'remove') return BUS.textarea.classList.remove(className); 21 | } 22 | 23 | /** 24 | * 修改文本框的锁定非锁定类名 25 | * @param {boolean} classState 26 | */ 27 | export function modifyTextareaLockState(classState: boolean) { 28 | if (classState) return modifyTextareaClass('add', 'lock'); 29 | return modifyTextareaClass('remove', 'lock'); 30 | } 31 | 32 | /** 33 | * 标注当前激活项的类型 home url local 三种 34 | * 提供相应按钮和背景 35 | * @param {string} className 36 | */ 37 | export function modifyTextareaType(className: string) { 38 | const list = ['local', 'home', 'net']; 39 | list.forEach((item) => { 40 | if (item === className) modifyTextareaClass('add', item); 41 | else modifyTextareaClass('remove', item); 42 | }); 43 | } 44 | 45 | /** 46 | * CodeMirror事件文本内容被修改时浮现保存按钮 47 | * @param {Object} CodeMirror 文本编辑器对象 48 | */ 49 | export function changeTextareaTip(CodeMirror: any) { 50 | const id = BUS.textarea.dataset.id; 51 | const flag = dataAction.inconformity(id, CodeMirror.getValue()); 52 | if (flag) modifyTextareaClass('add', 'save'); 53 | else modifyTextareaClass('remove', 'save'); 54 | return; 55 | } 56 | 57 | /** 58 | * 更新文本框内容 59 | */ 60 | export function eventTextareaUpdate() { 61 | const id = BUS.textarea.dataset.id; 62 | dataAction.asyncUpdateHosts(id); 63 | } 64 | 65 | /** 66 | * 保存文本框内容 67 | */ 68 | export function eventTextareaSave() { 69 | const id = BUS.textarea.dataset.id; 70 | const curItem = dataAction.getItemInfo(id); 71 | curItem.hosts = codeMirror.getValue(); 72 | dataAction.updateUseHosts(() => { 73 | modifyTextareaClass('remove', 'save'); 74 | tipSuccess('保存成功'); // 假提示 实际保存失败会再次提醒 75 | }); 76 | } 77 | -------------------------------------------------------------------------------- /web_source/src/js/types/aardio.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare namespace aardio { 4 | interface IProxy { 5 | ua?: string; 6 | host: string; 7 | user?: string; 8 | password?: string; 9 | } 10 | 11 | interface External { 12 | /** 获取系统HOSTS文本 */ 13 | getSystemHosts(): Promise; 14 | /** 保存到系统HOSTS文本 */ 15 | saveSystemHosts(content: string): Promise; 16 | /** 清理DNS缓存 */ 17 | clearDnsCache(): Promise; 18 | /** 发送请求获取网络HOSTS */ 19 | requestHosts(url: string, proxy?: IProxy): Promise<{ code: string; message: string; html?: string }>; 20 | /** 备份系统文件 */ 21 | backupLocalHosts(coverage?: boolean): Promise; 22 | /** 读取全部数据 */ 23 | getConfigData(): Promise; 24 | /** 保存全部数据 */ 25 | saveConfigData(data: Object): Promise; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /web_source/src/js/util.ts: -------------------------------------------------------------------------------- 1 | import LightTip from 'lu2/theme/pure/js/common/ui/LightTip'; 2 | import * as aardio from 'aardio'; 3 | 4 | /* 工具函数 */ 5 | 6 | /** 7 | * 成功tip 8 | * @param {string} text 9 | * @param {number} duration 毫秒 10 | */ 11 | export function tipSuccess(text: string, duration?: number) { 12 | new LightTip(text ?? '操作成功', { 13 | type: 'success', 14 | duration: duration ?? 3000, 15 | }); 16 | } 17 | 18 | /** 19 | * 异常tip 20 | * @param {string} text 21 | */ 22 | export function tipWarning(text: string) { 23 | new LightTip(text ?? '操作异常', { type: 'warning', duration: 3000 }); 24 | } 25 | 26 | /** 27 | * 失败tip 28 | * @param {string} text 29 | * @param {number} duration 毫秒 30 | */ 31 | export function tipError(text: string, duration?: number) { 32 | new LightTip(text ?? '操作失败', { 33 | type: 'error', 34 | duration: duration ?? 3000, 35 | }); 36 | } 37 | 38 | /* aardio相关操作 */ 39 | 40 | /** 41 | * 获取本地Hosts 42 | */ 43 | export function getSystemHosts() { 44 | return aardio.getSystemHosts().catch((e) => { 45 | tipError(e); 46 | return false; 47 | }); 48 | } 49 | 50 | /** 51 | * 保存到本地Hosts 52 | * @param {string} content 53 | */ 54 | export function saveSystemHosts(content: string) { 55 | return aardio 56 | .saveSystemHosts(content) 57 | .then((res) => { 58 | if (!res) tipError('写入失败,请用管理员权限启动再重试'); 59 | return res; 60 | }) 61 | .catch((e) => tipError(e)); 62 | } 63 | 64 | /** 65 | * 发送请求获取网络Hosts 66 | * @param {string} url 67 | * @param {aardio.IProxy} proxy 68 | */ 69 | export function requestHosts(url: string, proxy?: aardio.IProxy) { 70 | return aardio.requestHosts(url, proxy).catch((e) => ({ code: 9, message: '程序调用错误', html: '' })); 71 | } 72 | 73 | /** 74 | * 刷新DNS缓存 75 | */ 76 | export function refreshDnsCache() { 77 | aardio 78 | .clearDnsCache() 79 | .then((res) => { 80 | console.log('ers', res); 81 | }) 82 | .catch((e) => tipError('程序调用错误')); 83 | tipSuccess('刷新完成'); 84 | return; 85 | } 86 | 87 | /** 88 | * 备份系统文件 89 | * @param {boolean} coverage 90 | */ 91 | export function backupLocalHosts(coverage?: boolean) { 92 | return aardio.backupLocalHosts(coverage).catch((e) => ({ code: 9, message: e })); 93 | } 94 | 95 | /** 96 | * 读取全部数据 97 | */ 98 | export function getConfigData() { 99 | return aardio 100 | .getConfigData() 101 | .then((res) => { 102 | if (res.main) return res.main; 103 | else return null; 104 | }) 105 | .catch((e) => { 106 | tipError('读取数据失败'); 107 | return false; 108 | }); 109 | } 110 | 111 | /** 112 | * 保存全部数据 113 | */ 114 | export function saveConfigData(data: Object) { 115 | return aardio.saveConfigData(data).catch((e) => { 116 | tipError('保存数据失败'); 117 | return false; 118 | }); 119 | } 120 | -------------------------------------------------------------------------------- /web_source/src/lib/template.js: -------------------------------------------------------------------------------- 1 | /*! art-template@4.13.1 for browser | https://github.com/aui/art-template */ 2 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.template=t():e.template=t()}("undefined"!=typeof self?self:this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var n={};return t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e["default"]}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=4)}([function(e,t,n){"use strict";var r=n(6),i=n(2),o=n(22),s=function(e,t){t.onerror(e,t);var n=function(){return"{Template Error}"};return n.mappings=[],n.sourcesContent=[],n},a=function u(e){var t=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{};"string"!=typeof e?t=e:t.source=e,t=i.$extend(t),e=t.source,!0===t.debug&&(t.cache=!1,t.minimize=!1,t.compileDebug=!0),t.compileDebug&&(t.minimize=!1),t.filename&&(t.filename=t.resolveFilename(t.filename,t));var n=t.filename,a=t.cache,c=t.caches;if(a&&n){var l=c.get(n);if(l)return l}if(!e)try{e=t.loader(n,t),t.source=e}catch(m){var f=new o({name:"CompileError",path:n,message:"template not found: "+m.message,stack:m.stack});if(t.bail)throw f;return s(f,t)}var p=void 0,h=new r(t);try{p=h.build()}catch(f){if(f=new o(f),t.bail)throw f;return s(f,t)}var d=function(e,n){try{return p(e,n)}catch(f){if(!t.compileDebug)return t.cache=!1,t.compileDebug=!0,u(t)(e,n);if(f=new o(f),t.bail)throw f;return s(f,t)()}};return d.mappings=p.mappings,d.sourcesContent=p.sourcesContent,d.toString=function(){return p.toString()},a&&n&&c.set(n,d),d};a.Compiler=r,e.exports=a},function(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t["default"]=/((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyu]{1,5}\b(?![\u0080-\uFFFF$\\]|\s*(?:[+\-*%&|^<>!=?({]|\/(?![\/*])))))|(0[xX][\da-fA-F]+|0[oO][0-7]+|0[bB][01]+|(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)|((?!\d)(?:(?!\s)[$\w\u0080-\uFFFF]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+)|(--|\+\+|&&|\|\||=>|\.{3}|(?:[+\-\/%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2})=?|[?~.,:;[\](){}])|(\s+)|(^$|[\s\S])/g,t.matchToToken=function(e){var t={type:"invalid",value:e[0]};return e[1]?(t.type="string",t.closed=!(!e[3]&&!e[4])):e[5]?t.type="comment":e[6]?(t.type="comment",t.closed=!!e[7]):e[8]?t.type="regex":e[9]?t.type="number":e[10]?t.type="name":e[11]?t.type="punctuator":e[12]&&(t.type="whitespace"),t}},function(e,t,n){"use strict";function r(){this.$extend=function(e){return e=e||{},o(e,e instanceof r?e:this)}}var i=n(10),o=n(12),s=n(13),a=n(14),u=n(15),c=n(16),l=n(17),f=n(18),p=n(19),h=n(21),d="undefined"==typeof window,m={source:null,filename:null,rules:[f,l],escape:!0,debug:!!d&&"production"!==process.env.NODE_ENV,bail:!0,cache:!0,minimize:!0,compileDebug:!1,resolveFilename:h,include:s,htmlMinifier:p,htmlMinifierOptions:{collapseWhitespace:!0,minifyCSS:!0,minifyJS:!0,ignoreCustomFragments:[]},onerror:a,loader:c,caches:u,root:"/",extname:".art",ignore:[],imports:i};r.prototype=m,e.exports=new r},function(e,t){},function(e,t,n){"use strict";var r=n(5),i=n(0),o=n(23),s=function(e,t){return t instanceof Object?r({filename:e},t):i({filename:e,source:t})};s.render=r,s.compile=i,s.defaults=o,e.exports=s},function(e,t,n){"use strict";var r=n(0),i=function(e,t,n){return r(e,n)(t)};e.exports=i},function(e,t,n){"use strict";function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t|\([\w\W]*?\))\s*{[\s;]*$)/,"$1})"],[/(^[\w\W]*?\([\w\W]*?\)\s*{[\s;]*$)/,"$1}"]],n=0;n2&&arguments[2]!==undefined?arguments[2]:{},o=[new i("string",e)],s=0;sd&&(p=new i("string",v.slice(d,h.index),p),m.push(p)),p=new i("expression",h[0],p),h[0]=r(p),p.script=a.use.apply(n,h),m.push(p),d=h.index+h[0].length;d]/;o.$escape=function(e){return r(n(e))},o.$each=function(e,t){if(Array.isArray(e))for(var n=0,r=e.length;n {{"+n+"}}")};switch("#"===t&&h("#value","@value"),p){case"set":i="var "+u.join("").trim();break;case"if":i="if("+u.join("").trim()+"){";break;case"else":var d=u.indexOf("if");~d?(u.splice(0,d+1),i="}else if("+u.join("").trim()+"){"):i="}else{";break;case"/if":i="}";break;case"each":l=r._split(a),l.shift(),"as"===l[1]&&(h("each object as value index","each object value index"),l.splice(1,1));i="$each("+(l[0]||"$data")+",function("+(l[1]||"$value")+","+(l[2]||"$index")+"){";break;case"/each":i="})";break;case"block":l=r._split(a),l.shift(),i="block("+l.join(",").trim()+",function(){";break;case"/block":i="})";break;case"echo":p="print",h("echo value","value");case"print":case"include":case"extend":if(0!==u.join("").trim().indexOf("(")){l=r._split(a),l.shift(),i=p+"("+l.join(",")+")";break}default:if(~u.indexOf("|")){var m=a.reduce(function(e,t){var n=t.value,r=t.type;return"|"===n?e.push([]):"whitespace"!==r&&"comment"!==r&&(e.length||e.push([]),":"===n&&1===e[e.length-1].length?h("value | filter: argv","value | filter argv"):e[e.length-1].push(t)),e},[]).map(function(e){return r._split(e)});i=m.reduce(function(e,t){var n=t.shift();return t.unshift(e),"$imports."+n+"("+t.join(",")+")"},m.shift().join(" ").trim())}f=f||"escape"}return c.code=i,c.output=f,c},_split:function(e){e=e.filter(function(e){var t=e.type;return"whitespace"!==t&&"comment"!==t});for(var t=0,n=e.shift(),r=/\]|\)/,i=[[n]];t/,use:function(e,t,n,r){return n={"-":"raw","=":"escape","":!1,"==":"raw","=#":"raw"}[n],t&&(r="/*"+r+"*/",n=!1),{code:r,output:n}}};e.exports=r},function(e,t,n){"use strict";function r(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t> ":" ")+n+"| "+e}).join("\n");return(r||"anonymous")+":"+i+":"+o+"\n"+f+"\n\n"+t+": "+a+(s?"\n generated: "+s:"")}var a=function(e){function t(e){r(this,t);var n=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e.message));return n.name="TemplateError",n.message=s(e),Error.captureStackTrace&&Error.captureStackTrace(n,n.constructor),n}return o(t,e),t}(Error);e.exports=a},function(e,t,n){"use strict";e.exports=n(2)}])}); -------------------------------------------------------------------------------- /web_source/src/styles/base.less: -------------------------------------------------------------------------------- 1 | ul { 2 | margin: 0; 3 | padding: 0; 4 | } 5 | li { 6 | list-style-type: none; 7 | } 8 | html, 9 | body, 10 | nav, 11 | nav ul { 12 | height: 100%; 13 | overflow: hidden; 14 | } 15 | body { 16 | background-color: #eef0f5; 17 | } 18 | 19 | .clearfix { 20 | *zoom: 1; 21 | &:before, 22 | &:after { 23 | display: table; 24 | content: ""; 25 | } 26 | &:after { 27 | clear: both; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /web_source/src/styles/index.less: -------------------------------------------------------------------------------- 1 | @import './base.less'; 2 | @import './ui.less'; 3 | 4 | .container { 5 | height: 100%; 6 | width: 100%; 7 | position: relative; 8 | display: flex; 9 | justify-content: space-between; 10 | } 11 | 12 | /* 导航栏 */ 13 | .container nav { 14 | flex: 0 0 200px; 15 | height: auto; 16 | width: 200px; 17 | position: relative; 18 | 19 | ul { 20 | padding: 4px 2px 2px 0; 21 | overflow: auto; 22 | &::-webkit-scrollbar { 23 | width: 3px; 24 | } 25 | &::-webkit-scrollbar-thumb { 26 | border-radius: 10px; 27 | background: #bcd; 28 | } 29 | &::-webkit-scrollbar-track { 30 | border-radius: 0; 31 | background: #eef0f5; 32 | } 33 | } 34 | 35 | li { 36 | cursor: default; 37 | font-size: 13px; 38 | height: 40px; 39 | line-height: 40px; 40 | padding-left: 32px; 41 | position: relative; 42 | background: url('~/asset/record.svg') no-repeat 10px; 43 | background-size: 15px; 44 | color: #666666; 45 | border-left: 3px solid #eef0f5; 46 | opacity: 0.6; 47 | 48 | &.home { 49 | background: url('~/asset/home.svg') no-repeat 10px; 50 | background-size: 15px; 51 | } 52 | &.net { 53 | background: url('~/asset/recordFind.svg') no-repeat 10px; 54 | background-size: 15px; 55 | } 56 | &.mouse { 57 | background-color: #bedff7; 58 | border-left: 3px solid #51b0f5; 59 | } 60 | 61 | &.active, 62 | &:hover { 63 | background-color: #bedff7; 64 | border-left: 3px solid #51b0f5; 65 | opacity: 1; 66 | border-radius: 2px; 67 | } 68 | 69 | &:hover .option { 70 | cursor: pointer; 71 | position: absolute; 72 | width: 18px; 73 | height: 40px; 74 | right: 43px; 75 | top: 0px; 76 | background: url('~/asset/edit.svg') no-repeat center; 77 | background-size: 15px; 78 | opacity: 0.5; 79 | &:hover { 80 | opacity: 0.9; 81 | } 82 | } 83 | 84 | .onoff { 85 | position: absolute; 86 | right: 10px; 87 | top: 4px; 88 | } 89 | } 90 | 91 | &::after { 92 | content: 'LnnCoCo'; 93 | position: absolute; 94 | bottom: 2px; 95 | left: 2px; 96 | color: rgba(204, 204, 204, 0.6); 97 | font-size: 12px; 98 | transform: scale(0.9); 99 | cursor: default; 100 | } 101 | } 102 | 103 | /* 内容框 */ 104 | .container main { 105 | flex: 1; 106 | 107 | .textarea { 108 | background-color: #fff; 109 | border: 1px solid #ddd; 110 | border-radius: 3px; 111 | height: 98%; 112 | margin-top: 3px; 113 | margin-right: 3px; 114 | box-shadow: 0 0px 1px rgba(0, 0, 0, 0.1); 115 | 116 | textarea { 117 | height: 100%; 118 | width: 100%; 119 | border: none; 120 | outline: none; 121 | font-size: 15px; 122 | } 123 | 124 | // 背景 125 | .background-image-layer() { 126 | content: ''; 127 | position: absolute; 128 | width: 50%; 129 | height: 62%; 130 | right: 5px; 131 | bottom: 5px; 132 | opacity: 0.06; 133 | } 134 | &.local .CodeMirror::before { 135 | .background-image-layer(); 136 | background: url('~/asset/record.svg') no-repeat right bottom; 137 | background-size: contain; 138 | } 139 | &.net .CodeMirror::before { 140 | .background-image-layer(); 141 | background: url('~/asset/recordFind.svg') no-repeat right bottom; 142 | background-size: contain; 143 | } 144 | &.lock .CodeMirror::before { 145 | .background-image-layer(); 146 | background: url('~/asset/lock.svg') no-repeat right bottom; 147 | background-size: contain; 148 | } 149 | &.home .CodeMirror::before { 150 | .background-image-layer(); 151 | background: url('~/asset/home.svg') no-repeat right bottom; 152 | background-size: contain; 153 | } 154 | 155 | // 操作按钮 156 | &.home .operation { 157 | display: block; 158 | .refresh { 159 | display: inline-block; 160 | } 161 | } 162 | &.net .operation { 163 | display: block; 164 | .net { 165 | display: inline-block; 166 | } 167 | } 168 | &.save .operation { 169 | display: block; 170 | .save { 171 | display: inline-block; 172 | } 173 | } 174 | 175 | .operation { 176 | display: none; 177 | position: absolute; 178 | z-index: 110; 179 | top: 17px; 180 | right: 22px; 181 | background-color: rgba(189, 189, 189, 0.226); 182 | height: 20px; 183 | padding: 2px 13px; 184 | border-radius: 16px; 185 | transition: all 0.2s; 186 | 187 | .operation-icon() { 188 | display: none; 189 | width: 17px; 190 | height: 20px; 191 | opacity: 0.2; 192 | margin: 0 3px; 193 | &:hover { 194 | cursor: pointer; 195 | opacity: 0.6; 196 | } 197 | } 198 | 199 | .refresh { 200 | .operation-icon(); 201 | background: url('~/asset/refresh.svg') no-repeat center; 202 | background-size: contain; 203 | } 204 | 205 | .net { 206 | .operation-icon(); 207 | background: url('~/asset/download.svg') no-repeat center; 208 | background-size: contain; 209 | } 210 | 211 | .save { 212 | .operation-icon(); 213 | background: url('~/asset/save.svg') no-repeat center; 214 | background-size: contain; 215 | } 216 | } 217 | } 218 | } 219 | 220 | /* 弹窗样式 */ 221 | .dialog-item { 222 | position: absolute; 223 | left: 50%; 224 | top: 50%; 225 | transform: translate(-50%, -50%); 226 | width: 360px; 227 | background-color: #fff; 228 | border: 1px solid #ccc; 229 | border-radius: 3px; 230 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15); 231 | display: none; 232 | z-index: 100; 233 | 234 | &.active { 235 | display: block; 236 | } 237 | .item-hader { 238 | height: 40px; 239 | line-height: 40px; 240 | padding-left: 15px; 241 | border-bottom: 1px solid #e8e8e8; 242 | font-size: 15px; 243 | } 244 | .item-operation { 245 | overflow: hidden; 246 | padding: 10px; 247 | border-top: 1px solid #e8e8e8; 248 | 249 | .ui-button { 250 | float: right; 251 | & + .ui-button { 252 | margin-right: 10px; 253 | } 254 | } 255 | } 256 | .item-body { 257 | padding: 20px 40px; 258 | font-size: 14px; 259 | .form-item + .form-item { 260 | margin-top: 15px; 261 | } 262 | input { 263 | width: 200px; 264 | font-size: 13px; 265 | } 266 | } 267 | } 268 | 269 | .shade { 270 | display: none; 271 | position: absolute; 272 | top: 0; 273 | left: 0; 274 | width: 100%; 275 | height: 100%; 276 | background: rgba(0, 0, 0, 0.3); 277 | z-index: 99; 278 | } 279 | 280 | /* 右键菜单 */ 281 | .context-menu { 282 | position: absolute; 283 | width: 111px; 284 | padding: 5px 0; 285 | background-color: #fff; 286 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25); 287 | border: 1px solid #d0d0d5; 288 | border-radius: 2px; 289 | font-size: 14px; 290 | animation: fadeIn 0.2s; 291 | z-index: 200; 292 | left: -99999px; 293 | top: -99999px; 294 | .menu-item { 295 | display: block; 296 | line-height: 20px; 297 | padding: 8px 10px 7px; 298 | color: #4c5161; 299 | text-decoration: none; 300 | cursor: pointer; 301 | white-space: nowrap; 302 | text-overflow: ellipsis; 303 | overflow: hidden; 304 | &:hover { 305 | background-color: #f0f7ff; 306 | } 307 | &.disabled { 308 | cursor: default; 309 | pointer-events: none; 310 | opacity: 0.4; 311 | &:hover { 312 | background-color: transparent; 313 | } 314 | } 315 | .icon { 316 | display: inline-block; 317 | width: 13px; 318 | height: 13px; 319 | transform: translateY(2px); 320 | img { 321 | width: 100%; 322 | height: 100%; 323 | } 324 | } 325 | } 326 | .menu-line { 327 | border: 0; 328 | border-bottom: 1px solid #d0d0d5; 329 | margin: 7px 11px; 330 | opacity: 0.4; 331 | } 332 | .menu-target { 333 | cursor: default; 334 | padding-top: 2px; 335 | padding-bottom: 6px; 336 | font-size: 12px; 337 | color: #b9b9b9b0; 338 | height: 12px; 339 | line-height: 12px; 340 | transform: scale(0.8); 341 | } 342 | } 343 | -------------------------------------------------------------------------------- /web_source/src/styles/ui.less: -------------------------------------------------------------------------------- 1 | /* 控制Input大小 */ 2 | body { 3 | input.ui-input, 4 | .ui-input > input { 5 | height: 30px; 6 | } 7 | } 8 | 9 | /* 控制Button大小 */ 10 | body { 11 | .ui-button { 12 | min-width: 65px; 13 | line-height: 10px; 14 | } 15 | input.ui-button, 16 | button.ui-button { 17 | height: 30px; 18 | } 19 | } 20 | 21 | /* 控制switch大小 */ 22 | .container { 23 | .ui-switch { 24 | width: 26px; 25 | height: 16px; 26 | } 27 | :checked + .ui-switch::before { 28 | margin-left: 10px; 29 | } 30 | .ui-switch::before { 31 | width: 12px; 32 | height: 12px; 33 | } 34 | } 35 | 36 | /* 控制lightip大小 */ 37 | body { 38 | .ui-lightip { 39 | width: 20em; 40 | padding: 10px 1em; 41 | opacity: 0.8; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /web_source/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "baseUrl": ".", 5 | "paths": { 6 | "~*": ["./src/*"] 7 | }, 8 | "lib": [ 9 | "es2016", 10 | "dom" 11 | ] 12 | } 13 | } --------------------------------------------------------------------------------