Compare commits

...
189 Commits
Author SHA1 Message Date
whyour a3cbf8cdf4 迁移文件 2023-01-04 17:04:02 +08:00
whyour 0eab181d46 修改update逻辑 2022-12-29 12:15:25 +08:00
whyour f6f95308c7 monaco editor改为本地加载 2022-12-28 22:12:37 +08:00
whyour e93cad91b4 更新版本 v2.15.4 2022-12-28 11:15:20 +08:00
whyour 08ee61b179 修改 pub 脚本 2022-12-28 11:14:57 +08:00
whyour 0ab756665e 修改版本文件 2022-12-28 11:06:47 +08:00
whyour 3570cddce0 关于增加更新日志查看 2022-12-27 17:10:21 +08:00
whyour a2d9f1a5db 脚本管理支持重命名文件/文件夹 2022-12-27 16:02:15 +08:00
whyour 0c6a214e55 修复启动public服务命令 2022-12-27 12:24:24 +08:00
whyour 095fcdbe69 修复任务脚本快捷跳转 2022-12-17 12:46:26 +08:00
whyour 3afb1d18f6 更新版本 v2.15.3 2022-12-10 19:06:39 +08:00
whyour 4526c84330 任务视图支持标签筛选 2022-12-10 19:00:03 +08:00
whyour a9cc1cb4b9 修改token获取逻辑 2022-12-10 17:12:45 +08:00
whyour 7acf1eace3 修改添加任务视图筛选条件交互 2022-12-09 23:34:23 +08:00
whyour bb2e8cb287 修复调试保存文件默认目录和任务视图创建 2022-12-09 22:59:38 +08:00
whyour 3b389259c1 修复调试脚本日志 2022-12-06 00:22:05 +08:00
whyour 310ce55b09 修改默认基础镜像 2022-12-05 23:49:33 +08:00
CoolBoyandwhyour 4662e3fec2 修复notify.js中智能微秘书 (#1736) 2022-12-05 23:44:34 +08:00
whyour 10fab9d415 修改进程默认退出信号 2022-12-05 21:00:14 +08:00
whyour acecf01cbe 修复 killTask 返回值 2022-12-05 15:38:21 +08:00
whyour b95fb9cda4 修改退出进程逻辑 2022-12-05 15:26:22 +08:00
whyour 23fd595582 修改 timeout 命令默认信号 2022-12-05 13:18:10 +08:00
whyour 468d05cb10 更新版本 v2.15.2 2022-12-02 18:07:54 +08:00
whyour 88c2e5d160 更新 readme 2022-12-02 18:07:21 +08:00
whyour 8cf491b802 task 命令增加 -m 参数,支持设置任务超时时间 2022-12-01 18:26:24 +08:00
whyour 5886e78299 修复获取更新分支 2022-12-01 16:25:02 +08:00
whyour 591ef9781c 修改获取 cpu 占用 2022-12-01 16:16:17 +08:00
whyour 52fef96c1c 修改check逻辑 2022-11-30 21:29:58 +08:00
whyour d5fd9c57ec 修复shell语法 2022-11-29 22:50:11 +08:00
whyour 8a7d6a1c13 修改资源检查逻辑 2022-11-29 21:01:28 +08:00
whyour 1745c72981 修改 check/update 逻辑 2022-11-29 00:05:50 +08:00
whyour b98b7646cb 修复日志样式 2022-11-28 23:59:23 +08:00
whyour 1446e925ec 任务视图增加系统视图 2022-11-26 20:34:07 +08:00
whyour 799cda1e3e 移除未使用依赖 2022-11-24 22:09:33 +08:00
whyour d2e0231341 修改 workflow node_modules 缓存 2022-11-22 21:33:03 +08:00
whyour 9e0aa655a0 修改 workflow 依赖缓存 2022-11-22 21:00:53 +08:00
whyour e303c73d44 workflow 增加 digest 打印 2022-11-22 20:03:56 +08:00
whyour e5e8e66d6b 增加 docker action 缓存 2022-11-22 19:53:02 +08:00
whyour 0bb3381122 修复拉去仓库逻辑 2022-11-22 16:51:57 +08:00
whyour 2c5bf2bd6b 更新 readme 2022-11-22 14:42:27 +08:00
whyour 83763b00ae 上传 pnpm-lock 2022-11-22 13:41:39 +08:00
whyour 47fc795c97 增加action缓存 2022-11-22 13:37:44 +08:00
whyour 6a59bf7af3 更新版本 v2.15.1 2022-11-20 21:04:58 +08:00
whyour 6f185570d6 pushDeer支持自架版 2022-11-20 20:05:02 +08:00
whyour 8b8336d9d0 系统升级增加gitee源 2022-11-17 22:01:47 +08:00
whyour a1e1d6ed3f 更新 readme 2022-11-17 11:47:44 +08:00
whyour df3e209534 修改 workflow 2022-11-17 11:37:45 +08:00
whyour 851408860e 修复 workflow 2022-11-17 11:18:15 +08:00
whyour d92ea23b0e 修改 workflow 2022-11-17 11:11:05 +08:00
whyour d83641db92 修复workflow 2022-11-17 00:28:28 +08:00
whyour 48f262e1f3 增加 workflow 2022-11-17 00:23:24 +08:00
whyour bc49a7db50 同步gitee 2022-11-16 23:04:39 +08:00
whyour 49975b461c 修改typescript版本 2022-11-16 22:52:34 +08:00
whyour 3ccb635956 修复移动端最后更新时间展示 2022-11-16 22:34:28 +08:00
whyour 074a90e0ac 修改同步gitlab私钥 2022-11-16 00:02:40 +08:00
whyour 526f927436 增加 gitlab workflow 2022-11-15 23:55:28 +08:00
whyour fae7fad915 更新版本 v2.15.0 2022-11-15 12:15:06 +08:00
whyour 56132ceb8b 修复初始化新增字段 2022-11-15 12:14:33 +08:00
whyour 3c3fce0a5a 修复初始化表字段 2022-11-15 11:32:42 +08:00
whyour 8139384961 移除filterRelation默认值 2022-11-14 23:31:27 +08:00
whyour 734cc94048 修改filterRelation字段限制 2022-11-14 22:59:01 +08:00
whyour 91dbb7770d 修改订阅github ssh生成逻辑 2022-11-14 22:00:16 +08:00
whyour 707709837d 初始化更新不存在filterRelation的任务视图 2022-11-14 21:36:31 +08:00
whyour e868e65208 修改日志管理默认排序 2022-11-14 15:12:17 +08:00
whyour b19ad2a13b 修复debounce方法引入错误 2022-11-14 11:35:51 +08:00
whyour 98ccccf6ab 修复openapi token生成逻辑 2022-11-14 09:28:30 +08:00
whyour 0a6166c557 订阅增加代理参数 2022-11-13 23:58:42 +08:00
whyour 5ee00e52a8 修复新建视图筛选条件样式 2022-11-13 22:12:03 +08:00
whyour ff2b4e0b2f 订阅支持添加代理 2022-11-12 22:45:46 +08:00
whyour 8fdd8db51b 修改创建任务视图样式 2022-11-11 15:03:27 +08:00
whyour f113eb7ba8 修改系统设置样式 2022-11-11 14:55:09 +08:00
whyour 40bc25ed5f 修复获取最后commit时间 2022-11-10 10:52:57 +08:00
whyour cd3eab5d35 修复版本信息展示 2022-11-10 01:34:18 +08:00
whyour 7038e15ad2 支持定时任务视图筛选条件关系切换 2022-11-10 01:31:21 +08:00
whyour c72abd29ec 任务视图筛选条件增加条件关系 2022-11-09 20:43:22 +08:00
whyour 5efc3d2228 更新版本 v2.14.12 2022-11-05 16:43:28 +08:00
whyour 8ac3f83c79 修复可能出现移动或者创建环境变量出错 2022-11-05 16:41:19 +08:00
whyour b31b054d0c 更新版本 v2.14.11 2022-11-05 15:24:16 +08:00
whyour fb4a87f5ce 修复版本文件缓存 2022-11-05 15:23:17 +08:00
whyour 049c73880b 修改pre样式 2022-11-05 14:57:21 +08:00
whyour 7b2c54f6a6 修改版本信息获取 2022-11-05 12:14:46 +08:00
whyour 23bda39812 关于增加版本信息展示 2022-11-05 11:01:58 +08:00
whyour 90af5801ee 修复表格滚动 2022-11-04 19:14:03 +08:00
whyour 543c241bc6 更新版本 v2.14.10 2022-11-03 21:16:46 +08:00
whyour 19a58a3510 环境变量值增加复制功能 2022-11-03 17:34:36 +08:00
whyour 73c6fd18ed 修复资源预警通知 2022-11-03 13:42:14 +08:00
whyour 409297c6aa 修改调试日志样式 2022-11-02 19:54:49 +08:00
whyour 4272b9ea35 修复task命令参数 2022-11-02 19:40:16 +08:00
whyour 3c5c5b0bbc 修复&符号转义 2022-11-02 19:25:03 +08:00
whyour 802b2d722e 修复任务命令中的&和引号 2022-11-02 18:51:09 +08:00
whyour 8f90d3f8ff 修复环境变量位置计算逻辑 2022-11-02 00:02:15 +08:00
whyour f93cbbf508 修复 notify.js 飞书通知 2022-10-30 18:59:48 +08:00
whyour 2ba8756bd3 修改cdn协议 2022-10-30 12:00:12 +08:00
whyour 8013de56c9 修改sqlite配置 2022-10-30 10:54:39 +08:00
whyour 4af9b22442 更新版本 v2.14.9 2022-10-29 18:50:16 +08:00
whyour 8a392170cf webhook通知支持嵌套body 2022-10-29 18:43:16 +08:00
whyour 6385e053ae 增加飞书机器人通知 2022-10-29 16:41:37 +08:00
Leo_chenandGitHub 2789119882 添加智能微秘书通知 (#1680) 2022-10-29 15:45:16 +08:00
whyour 3e0553c3e8 修改登陆逻辑 2022-10-29 10:05:54 +08:00
whyour 5e16ace1e7 修改检查更新日志 2022-10-27 10:34:55 +08:00
whyour 0ca23cc4ca 修改环境变量默认排序 2022-10-27 00:02:50 +08:00
whyour 4949457001 修复ql命令日志打印 2022-10-26 23:50:07 +08:00
whyour 8ae13fe823 增加 -max 指定环境变量 2022-10-26 14:27:14 +08:00
whyour fdf672092a 修改获取version文件超时时间 2022-10-25 23:52:30 +08:00
whyour 48dd6ea826 修复表格滚动高度 2022-10-25 23:12:38 +08:00
whyour 68bb4f15e2 修复shell获取磁盘使用量 2022-10-24 22:45:06 +08:00
whyour 9c6d9ec22d 更新版本 v2.14.8 2022-10-22 18:36:38 +08:00
whyour ac075ace73 修复调试脚本语言判断 2022-10-22 00:31:34 +08:00
whyour eb58774ee9 优化task.sh 2022-10-22 00:25:54 +08:00
whyour 04613bf9a9 修复tsconfig 2022-10-20 15:30:22 +08:00
whyour 4194f1964d 修改日志结束符判定 2022-10-20 15:16:17 +08:00
whyour 42c64c82d7 修复 ql 命令日志目录 2022-10-16 21:59:19 +08:00
whyour d44a8966f2 修复环境变量名称验证 2022-10-16 09:22:37 +08:00
whyour ff44330aa1 修复 ql 命令日志目录 2022-10-15 18:40:15 +08:00
whyour ed259e8168 修复 task 命令执行时参数引号丢失 2022-10-15 18:29:34 +08:00
whyour 444836975d 修改 ql 命令打印日志逻辑 2022-10-14 23:02:20 +08:00
whyour 3756fa93e4 修复 ql 命令 2022-10-14 21:17:04 +08:00
whyour 064b52b306 修改 timezone action 2022-10-14 20:55:58 +08:00
whyour 648dc51474 更新ql指令 2022-10-14 15:17:37 +08:00
whyour 7c0bc32759 修改环境变量导入 2022-10-13 23:41:54 +08:00
whyour d4b6cc5e4d 修复调试脚本选择脚本 2022-10-13 23:39:28 +08:00
whyour 75fca715e3 增加环境变量导入 2022-10-11 22:16:36 +08:00
whyour 6e9a4a29ef 修复shell语法 2022-10-09 13:49:19 +08:00
whyour 78f643c50f 更新版本v2.14.7 2022-10-01 23:12:57 +08:00
whyour 2db4f1ba87 修改资源判定逻辑 2022-10-01 23:04:12 +08:00
whyour 5741dbb78c 修复获取task_before参数 2022-09-30 15:32:42 +08:00
whyour 88cf671465 更新版本v2.14.6 2022-09-29 23:06:31 +08:00
whyour 29f082dea2 增加config资源配置 2022-09-29 23:03:22 +08:00
whyour 9a55968ed6 修改资源异常推送 2022-09-29 13:29:22 +08:00
whyour 6ec6e25855 修改资源提示 2022-09-29 00:59:27 +08:00
whyour af48bc378b 修复获取cpu占用 2022-09-29 00:57:31 +08:00
whyour 3f5ae4bcb9 修复 echo 2022-09-29 00:44:07 +08:00
whyour c6624e9001 增加资源占用提示 2022-09-29 00:43:07 +08:00
whyour 5530ce76e3 添加系统资源消耗提示 2022-09-29 00:32:17 +08:00
whyour 654b51e476 修复脚本和日志搜索逻辑 2022-09-25 21:03:11 +08:00
whyour 6428ac3624 修复SplitPane类型错误 2022-09-25 14:02:27 +08:00
whyour c36450f436 修复ant-tree高度获取 2022-09-25 13:38:10 +08:00
whyour dcea231249 更新版本 v2.14.5 2022-09-24 21:00:47 +08:00
whyour f236119bd6 修改输入框自动填充样式 2022-09-24 14:40:13 +08:00
whyour cb870fad85 修改检查更新逻辑 2022-09-24 14:20:35 +08:00
whyour 44e2caedfc 修改更新日志清除评率 2022-09-24 13:59:56 +08:00
whyour c0b5192296 修改移动端脚本高亮 2022-09-24 11:27:16 +08:00
whyour ba43882c0b 修复脚本管理删除 2022-09-23 23:16:57 +08:00
whyour dfc706e16d 日志管理支持删除日志文件和目录 2022-09-23 20:09:10 +08:00
whyour 25b03d4345 脚本管理支持删除文件夹 2022-09-23 19:12:51 +08:00
whyour 4e8f36d9a4 修复登录错误提示 2022-09-23 17:44:48 +08:00
whyour 8f4d67ffa7 修改task命令ID获取 2022-09-23 14:37:56 +08:00
whyour ad47277149 修复登录验证 2022-09-23 12:15:15 +08:00
whyour 98c2a37ab6 修复初始化逻辑 2022-09-23 00:17:53 +08:00
whyour f2fea47336 重构前端错误提示 2022-09-22 23:59:23 +08:00
whyour e274d3e2f9 sentry增加版本号 2022-09-22 12:14:42 +08:00
whyour 36f4c3c02c 修改任务启动参数 2022-09-21 21:28:31 +08:00
whyour ae891f8e55 修复docker启动逻辑 2022-09-21 17:42:13 +08:00
whyour c874dc9705 更新readme 2022-09-21 16:03:53 +08:00
whyour 23bfbeb995 修改新建订阅提示 2022-09-21 14:54:45 +08:00
whyour a75df03243 更新版本 2.14.4 2022-09-20 19:59:51 +08:00
whyour e44a2b5995 修改tsconfig 2022-09-20 19:43:49 +08:00
whyour f23e7a9e49 修复自定义通知 2022-09-20 19:13:11 +08:00
whyour e08f0cd308 修复设置自定义通知 2022-09-20 18:00:36 +08:00
whyour 1ebcfd8001 修复自定义通知 2022-09-20 17:34:36 +08:00
whyour 5168b044a3 修复遍历key值 2022-09-20 01:23:33 +08:00
whyour 931638b687 增加自定义hook通知 2022-09-20 01:16:36 +08:00
whyour 4d9bbcfd3f 升级antd 2022-09-19 18:45:56 +08:00
whyour b0e3b26369 修改环境变量默认排序 2022-09-18 20:47:42 +08:00
whyour 1e55f4065d 升级umi4.0,修复新建脚本 2022-09-18 20:40:59 +08:00
whyour 518e8903a3 兼容Modal属性 2022-09-17 22:50:58 +08:00
whyour 6e56a55f6f 修改弹框表单逻辑 2022-09-16 00:28:04 +08:00
whyour 967071ad4e 脚本管理支持新增文件夹 2022-09-16 00:14:10 +08:00
whyour d23fcfaa5a 修复创建应用 2022-09-15 23:45:12 +08:00
whyour a2f2306430 增加批量重新安装依赖 2022-09-11 22:47:43 +08:00
whyour 144b543091 修改依赖管理默认排序 2022-09-11 22:26:33 +08:00
whyour e4ad8f512e 修改订阅默认排序 2022-09-11 22:10:17 +08:00
whyour 591a5006da 修复运行任务shell 2022-09-11 19:53:57 +08:00
whyour 281ed6cfba 修改任务执行日志目录规则 2022-09-11 19:43:37 +08:00
whyour 7354a61184 修改config配置说明 2022-09-10 14:23:16 +08:00
whyour 04037f29e5 更新版本 v2.14.3 2022-09-10 14:12:26 +08:00
whyour 6b124bad89 修复pnpm registry兼容 2022-09-09 00:21:10 +08:00
whyour 54d99a4954 更新版本 v2.14.2 2022-09-07 19:30:19 +08:00
whyour 9947594366 更新issue模板 2022-09-07 17:28:57 +08:00
whyour d7ff934336 增加github issue模版 2022-09-07 16:03:15 +08:00
whyour dc27856441 修复定时任务状态筛选 2022-09-07 11:30:11 +08:00
whyour bd28682769 排除认证失败错误上报 2022-09-06 23:57:21 +08:00
whyour 2060e62da4 更新sentry版本 2022-09-06 21:50:03 +08:00
whyour 70eac1e747 修改pnpm安装全局模块命令 2022-09-06 15:53:21 +08:00
whyour 6f5a5fe066 修改定时任务打开详情交互 2022-09-06 14:49:42 +08:00
景大侠andGitHub 8d24949202 修复#1614 正确解析多级目录的脚本路径 (#1616) 2022-09-06 13:25:12 +08:00
whyour f7b6237355 修复新建任务视图交互 2022-09-06 00:40:06 +08:00
景大侠andGitHub daf6f94c51 修复任务视图bug (#1612)
* 修复了视图无排序时无法再次修改的问题

* 修复在视图管理中编辑、新建视图点击确定后不能关闭页面的问题

* 修复#1611 避免查询条件被覆盖

* 修复视图筛选不能正确处理`不包含`
2022-09-06 00:25:05 +08:00
whyour 687d16e21b 增加npm镜像源配置 2022-09-06 00:21:53 +08:00
197 changed files with 22525 additions and 3216 deletions
+42
View File
@@ -0,0 +1,42 @@
name: "\U0001F41E Bug report"
description: Create a report to help us improve
body:
- type: input
id: version
attributes:
label: Qinglong version
validations:
required: true
- type: textarea
id: steps-to-reproduce
attributes:
label: Steps to reproduce
description: |
What do we need to do after opening your repro in order to make the bug happen? Clear and concise reproduction instructions are important for us to be able to triage your issue in a timely manner. Note that you can use [Markdown](https://guides.github.com/features/mastering-markdown/) to format lists and code.
placeholder: Steps to reproduce
validations:
required: true
- type: textarea
id: expected
attributes:
label: What is expected?
validations:
required: true
- type: textarea
id: actually-happening
attributes:
label: What is actually happening?
validations:
required: true
- type: textarea
id: system-info
attributes:
label: System Info
description: Output of `npx envinfo --system --binaries --browsers`
render: shell
placeholder: System, Binaries, Browsers
- type: textarea
id: additional-comments
attributes:
label: Any additional comments?
description: e.g. some background/context of how you ran into this bug.
+8
View File
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Telegram Chat
url: https://t.me/jiao_long
about: Ask questions and discuss with other Qinglong users in real time.
- name: Questions & Discussions
url: https://github.com/whyour/qinglong/discussions/new?category=q-a
about: Use GitHub discussions for message-board style questions and discussions.
@@ -0,0 +1,40 @@
name: "\U0001F680 New feature proposal"
description: Suggest an idea for this project
labels: [":sparkles: feature request"]
body:
- type: markdown
attributes:
value: |
Thanks for your interest in the project and taking the time to fill out this feature report!
- type: textarea
id: feature-description
attributes:
label: Clear and concise description of the problem
description: "Explain your use case, context, and rationale behind this feature request. More importantly, what is the **end user experience** you are trying to build that led to the need for this feature?"
validations:
required: true
- type: textarea
id: suggested-solution
attributes:
label: Suggested solution
description: "In module [xy] we could provide following implementation..."
validations:
required: true
- type: textarea
id: alternative
attributes:
label: Alternative
description: Clear and concise description of any alternative solutions or features you've considered.
- type: textarea
id: additional-context
attributes:
label: Additional context
description: Any other context or screenshots about the feature request here.
- type: checkboxes
id: checkboxes
attributes:
label: Validations
description: Before submitting the issue, please make sure you do the following
options:
- label: Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
required: true
+31
View File
@@ -0,0 +1,31 @@
## PR Type
What kind of change does this PR introduce?
<!-- Please check the one that applies to this PR using "x". -->
- [ ] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, local variables)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Other... Please describe:
## What is the current behavior?
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->
Issue Number: N/A
## What is the new behavior?
## Does this PR introduce a breaking change?
- [ ] Yes
- [ ] No
<!-- If this PR contains a breaking change, please describe the impact and migration path for existing applications below. -->
## Other information
+7
View File
@@ -0,0 +1,7 @@
# Comment to be posted to on PRs from first time contributors in your repository
newPRWelcomeComment: |
💖 Thanks for opening this pull request! 💖
Please be patient and we will get back to you as soon as we can.
# Comment to be posted to on pull requests merged by a first time user
firstPRMergeComment: >
Congrats on merging your first pull request! 🎉🎉🎉
+60 -10
View File
@@ -17,16 +17,47 @@ on:
workflow_dispatch:
jobs:
to_gitlab:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: pixta-dev/repository-mirroring-action@v1
with:
target_repo_url:
git@gitlab.com:whyour/qinglong.git
ssh_private_key:
${{ secrets.GITLAB_SSH_PK }}
to_gitee:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: pixta-dev/repository-mirroring-action@v1
with:
target_repo_url:
git@gitee.com:whyour/qinglong.git
ssh_private_key:
${{ secrets.GITLAB_SSH_PK }}
build-static:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: latest
- uses: actions/setup-node@v3
with:
cache: 'pnpm'
- name: build front and back
run: |
npm i -g pnpm
pnpm install
pnpm install --frozen-lockfile
pnpm build:front
pnpm build:back
@@ -34,6 +65,9 @@ jobs:
env:
GITHUB_REPO: github.com/${{ github.repository_owner }}/qinglong-static
GITHUB_BRANCH: ${{ github.ref_name }}
REPO_GITEE: git@gitee.com:whyour/qinglong-static.git
REPO_GITLAB: git@gitlab.com:whyour/qinglong-static.git
PRIVATE_KEY: ${{ secrets.GITLAB_SSH_PK }}
run: |
mkdir -p tmp
cd ./tmp
@@ -44,6 +78,16 @@ jobs:
git commit --allow-empty -m "copy static at $(date +'%Y-%m-%d %H:%M:%S')"
git push --force --quiet "https://${{ secrets.API_TOKEN }}@${GITHUB_REPO}.git" ${GITHUB_BRANCH}:${GITHUB_BRANCH}
mkdir -p ~/.ssh
echo "${PRIVATE_KEY}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
export GIT_SSH_COMMAND="ssh -v -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no -l git"
git remote add gitee "${REPO_GITEE}"
git remote add gitlab "${REPO_GITLAB}"
git push --force --quiet gitee ${GITHUB_BRANCH}:${GITHUB_BRANCH}
git push --force --quiet gitlab ${GITHUB_BRANCH}:${GITHUB_BRANCH}
build:
needs: build-static
@@ -55,14 +99,17 @@ jobs:
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- name: Set time zone
uses: szenius/set-timezone@v1.0
- uses: pnpm/action-setup@v2
with:
timezoneLinux: "Asia/Shanghai"
timezoneMacos: "Asia/Shanghai"
timezoneWindows: "China Standard Time"
version: latest
- uses: actions/setup-node@v3
with:
cache: 'pnpm'
- name: Setup timezone
uses: zcong1993/setup-timezone@master
with:
timezone: Asia/Shanghai
- name: Login to DockerHub
uses: docker/login-action@v2
@@ -100,7 +147,7 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build and push
id: docker_build
uses: docker/build-push-action@v3
@@ -114,3 +161,6 @@ jobs:
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
+2 -2
View File
@@ -5,7 +5,6 @@
/npm-debug.log*
/yarn-error.log
/yarn.lock
/pnpm-lock.yaml
/package-lock.json
# production
@@ -29,4 +28,5 @@
/db
/manual_log
/scripts
/bak
/bak
node_modules
+10 -6
View File
@@ -1,6 +1,6 @@
<p align="center">
<a href="https://github.com/whyour/qinglong">
<img width="150" src="https://z3.ax1x.com/2021/11/18/I7MpAe.png">
<img width="150" src="https://user-images.githubusercontent.com/22700758/191449379-f9f56204-0e31-4a16-be5a-331f52696a73.png">
</a>
</p>
@@ -22,7 +22,7 @@ Timed task management panel with python3, javaScript, shell, typescript support
[docker-image-size-url]: https://hub.docker.com/r/whyour/qinglong
</div>
[![](https://user-images.githubusercontent.com/22700758/161788855-c4e51cb8-d4e9-44fe-bb17-ee1a56c8549b.png)](https://whyour.cn)
[![](https://user-images.githubusercontent.com/22700758/203243067-1a8a570d-b1b4-4837-9f12-d78d83e31f35.jpg)](https://whyour.cn)
[简体中文](./README.md) | English
@@ -41,7 +41,7 @@ Timed task management panel with python3, javaScript, shell, typescript support
### Local Deployment
```bash
# To be completed
# To be refined, see the development steps first (not supported on windows yet)
```
### Podman Deployment
@@ -61,7 +61,6 @@ podman run -dit \
-p 5700:5700 \
--name qinglong \
--hostname qinglong \
--restart unless-stopped \
docker.io/whyour/qinglong:latest
```
@@ -161,7 +160,11 @@ task <file_path> now
# the foreground does not generate the day, directly recorded in the log file, and can be specified account execution
task <file_path> conc <env_name> <account_number>(Optional)
# Specify the account to execute and run immediately regardless of whether a random delay is set
task <file_path> desi <env_name> <account_number>
task <file_path> desi <env_name> <account_number>
# Set task timeout
task -m <max_time> <file_path>
# Print task log in real time, no need to carry this parameter when creating timed tasks
task -l <file_path>
```
2. parameter description
@@ -176,6 +179,7 @@ task <file_path> desi <env_name> <account_number>
* file_path: File path for task execution
* env_name: The name of the environment variable that needs to be concurrent or specified at the time of task execution
* account_number: Specify the account number of an environment variable to be executed when the task is executed
* max_time: Timeout, suffix "s" for seconds (default), "m" for minutes, "h" for hours, "d" for days
## Links
@@ -183,7 +187,7 @@ task <file_path> desi <env_name> <account_number>
- [crontab-ui](https://github.com/alseambusher/crontab-ui)
- [Ant Design](https://ant.design)
- [Ant Design Pro](https://pro.ant.design/)
- [Umijs3.0](https://umijs.org)
- [Umijs](https://umijs.org)
- [darkreader](https://github.com/darkreader/darkreader)
- [admin-server](https://github.com/sunpu007/admin-server)
+10 -6
View File
@@ -1,6 +1,6 @@
<p align="center">
<a href="https://github.com/whyour/qinglong">
<img width="150" src="https://z3.ax1x.com/2021/11/18/I7MpAe.png">
<img width="150" src="https://user-images.githubusercontent.com/22700758/191449379-f9f56204-0e31-4a16-be5a-331f52696a73.png">
</a>
</p>
@@ -22,7 +22,7 @@
[docker-image-size-url]: https://hub.docker.com/r/whyour/qinglong
</div>
[![](https://user-images.githubusercontent.com/22700758/161788855-c4e51cb8-d4e9-44fe-bb17-ee1a56c8549b.png)](https://whyour.cn)
[![](https://user-images.githubusercontent.com/22700758/203243067-1a8a570d-b1b4-4837-9f12-d78d83e31f35.jpg)](https://whyour.cn)
简体中文 | [English](./README-en.md)
@@ -41,7 +41,7 @@
### 本机部署
```bash
# 待完善
# 待完善,可先参考开发步骤 (windows暂时不支持)
```
### podman 部署
@@ -61,7 +61,6 @@ podman run -dit \
-p 5700:5700 \
--name qinglong \
--hostname qinglong \
--restart unless-stopped \
docker.io/whyour/qinglong:latest
```
@@ -160,7 +159,11 @@ task <file_path> now
# 并发执行,无论是否设置了随机延迟,均立即运行,前台不产生日,直接记录在日志文件中,且可指定账号执行
task <file_path> conc <env_name> <account_number>(可选的)
# 指定账号执行,无论是否设置了随机延迟,均立即运行
task <file_path> desi <env_name> <account_number>
task <file_path> desi <env_name> <account_number>
# 设置任务超时时间
task -m <max_time> <file_path>
# 实时打印任务日志,创建定时任务时,不用携带此参数
task -l <file_path>
```
2. 参数说明
@@ -176,6 +179,7 @@ task <file_path> desi <env_name> <account_number>
* file_path: 任务执行时的文件路径
* env_name: 任务执行时需要并发或者指定时的环境变量名称
* account_number: 任务执行时指定某个环境变量需要执行的账号序号
* max_time: 超时时间,后缀"s"代表秒(默认值), "m"代表分, "h"代表小时, "d"代表天
## 链接
@@ -183,7 +187,7 @@ task <file_path> desi <env_name> <account_number>
- [crontab-ui](https://github.com/alseambusher/crontab-ui)
- [Ant Design](https://ant.design)
- [Ant Design Pro](https://pro.ant.design/)
- [Umijs3.0](https://umijs.org)
- [Umijs](https://umijs.org)
- [darkreader](https://github.com/darkreader/darkreader)
- [admin-server](https://github.com/sunpu007/admin-server)
+1 -1
View File
@@ -1,4 +1,4 @@
FROM python:alpine
FROM python:3.10-alpine
ARG QL_MAINTAINER="whyour"
LABEL maintainer="${QL_MAINTAINER}"
+6 -2
View File
@@ -4,6 +4,8 @@ dir_shell=/ql/shell
. $dir_shell/share.sh
link_shell
export isFirstStartServer=true
echo -e "======================1. 检测配置文件========================\n"
make_dir /etc/nginx/conf.d
make_dir /run/nginx
@@ -11,6 +13,8 @@ cp -fv $nginx_conf /etc/nginx/nginx.conf
cp -fv $nginx_app_conf /etc/nginx/conf.d/front.conf
sed -i "s,QL_BASE_URL,${qlBaseUrl},g" /etc/nginx/conf.d/front.conf
pm2 l &>/dev/null
patch_version &>/dev/null
echo
echo -e "======================2. 安装依赖========================\n"
@@ -38,13 +42,13 @@ echo -e "定时任务启动成功...\n"
if [[ $AutoStartBot == true ]]; then
echo -e "======================7. 启动bot========================\n"
nohup ql bot >>$dir_log/start.log 2>&1 &
nohup ql bot >$dir_log/bot.log 2>&1 &
echo -e "bot后台启动中...\n"
fi
if [[ $EnableExtraShell == true ]]; then
echo -e "======================8. 执行自定义脚本========================\n"
nohup ql extra >>$dir_log/start.log 2>&1 &
nohup ql extra >$dir_log/extra.log 2>&1 &
echo -e "自定义脚本后台执行中...\n"
fi
-6
View File
@@ -1,6 +0,0 @@
{
"watch": ["back", ".env"],
"ext": "js,ts,json",
"ignore": ["src/**/*.spec.ts"],
"exec": "ts-node --transpile-only ./back/app.ts"
}
+46 -25
View File
@@ -2,16 +2,17 @@
"private": true,
"scripts": {
"start": "concurrently -n w: npm:start:*",
"start:front": "umi dev",
"start:back": "nodemon",
"start:public": "ts-node back/public.ts",
"build:front": "umi build",
"start:env": "pnpm run --filter @qinglong/env start",
"start:front": "pnpm run --filter @qinglong/web start",
"start:back": "pnpm run --filter @qinglong/back start",
"start:public": "pnpm run --filter @qinglong/public start",
"build:front": "max build",
"build:back": "tsc -p tsconfig.back.json",
"panel": "npm run build:back && node static/build/app.js",
"schedule": "npm run build:back && node static/build/schedule.js",
"public": "npm run build:back && node static/build/public.js",
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
"postinstall": "umi generate tmp 2>/dev/null || true",
"postinstall": "max setup 2>/dev/null || true",
"test": "umi-test",
"test:coverage": "umi-test --coverage"
},
@@ -28,16 +29,33 @@
},
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"react",
"react-dom",
"antd",
"dva",
"postcss",
"webpack",
"eslint",
"stylelint",
"redux",
"@babel/core",
"monaco-editor",
"rc-field-form",
"@types/lodash.merge",
"rollup"
],
"allowedVersions": {
"react": "17",
"react-dom": "17"
"react": "18",
"react-dom": "18",
"dva-core": "2"
}
}
},
"dependencies": {
"@otplib/preset-default": "^12.0.1",
"@sentry/node": "^7.0.0",
"@sentry/tracing": "^7.0.0",
"@sentry/node": "^7.12.1",
"@sentry/tracing": "^7.12.1",
"body-parser": "^1.19.2",
"celebrate": "^15.0.1",
"chokidar": "^3.5.3",
@@ -48,18 +66,20 @@
"express": "^4.17.3",
"express-jwt": "^6.1.1",
"express-urlrewrite": "^1.4.0",
"form-data": "^4.0.0",
"got": "^11.8.2",
"hpagent": "^0.1.2",
"iconv-lite": "^0.6.3",
"js-yaml": "^4.1.0",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.21",
"multer": "^1.4.4",
"nedb": "^1.8.0",
"node-schedule": "^2.1.0",
"nodemailer": "^6.7.2",
"p-queue": "7.2.0",
"pstree.remy": "^1.1.8",
"reflect-metadata": "^0.1.13",
"sequelize": "^6.20.1",
"sequelize": "^6.25.5",
"serve-handler": "^6.1.3",
"sockjs": "^0.3.24",
"sqlite3": "npm:@louislam/sqlite3@^15.0.6",
@@ -72,54 +92,55 @@
"devDependencies": {
"@ant-design/icons": "^4.7.0",
"@ant-design/pro-layout": "^6.33.1",
"@monaco-editor/react": "^4.3.1",
"@sentry/react": "^7.0.0",
"@monaco-editor/react": "4.4.6",
"@react-hook/resize-observer": "^1.2.6",
"@sentry/react": "^7.12.1",
"@types/body-parser": "^1.19.2",
"@types/cors": "^2.8.12",
"@types/express": "^4.17.13",
"@types/express-jwt": "^6.0.4",
"@types/js-yaml": "^4.0.5",
"@types/jsonwebtoken": "^8.5.8",
"@types/lodash": "^4.14.179",
"@types/lodash": "^4.14.185",
"@types/multer": "^1.4.7",
"@types/nedb": "^1.8.12",
"@types/node": "^17.0.21",
"@types/node-schedule": "^1.3.2",
"@types/nodemailer": "^6.4.4",
"@types/qrcode.react": "^1.0.2",
"@types/react": "^17.0.39",
"@types/react-dom": "^17.0.13",
"@types/react": "^18.0.20",
"@types/react-dom": "^18.0.6",
"@types/serve-handler": "^6.1.1",
"@types/sockjs": "^0.3.33",
"@types/sockjs-client": "^1.5.1",
"@types/uuid": "^8.3.4",
"@umijs/plugin-antd": "^0.15.0",
"@umijs/plugin-esbuild": "^1.4.1",
"@umijs/max": "^4.0.21",
"@umijs/ssr-darkreader": "^4.9.45",
"@umijs/test": "^3.5.21",
"ansi-to-react": "^6.1.6",
"antd": "^4.20.5",
"antd": "^4.23.0",
"antd-img-crop": "^4.2.3",
"codemirror": "^5.65.2",
"compression-webpack-plugin": "9.2.0",
"concurrently": "^7.0.0",
"lint-staged": "^12.3.4",
"lint-staged": "^13.0.3",
"monaco-editor": "^0.34.1",
"nodemon": "^2.0.15",
"prettier": "^2.5.1",
"qiniu": "^7.4.0",
"qrcode.react": "^1.0.1",
"query-string": "^7.1.1",
"rc-tween-one": "^3.0.6",
"react": "17.x",
"react": "18.2.0",
"react-codemirror2": "^7.2.1",
"react-diff-viewer": "^3.1.1",
"react-dnd": "^14.0.2",
"react-dnd-html5-backend": "^14.0.0",
"react-dom": "17.x",
"react-dom": "18.2.0",
"react-split-pane": "^0.1.92",
"sockjs-client": "^1.6.0",
"ts-node": "^10.6.0",
"tslib": "^2.4.0",
"typescript": "^4.6.2",
"umi": "^3.5.21",
"typescript": "4.8.4",
"umi-request": "^1.4.0",
"vh-check": "^2.0.5",
"webpack": "^5.70.0",
+6
View File
@@ -0,0 +1,6 @@
{
"watch": ["src", ".env"],
"ext": "js,ts,json",
"ignore": ["src/**/*.spec.ts"],
"exec": "ts-node --transpile-only ./src/app.ts"
}
+138
View File
@@ -0,0 +1,138 @@
{
"name": "@qinglong/back",
"private": true,
"scripts": {
"start": "nodemon",
"build": "tsc"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,less,md,json}": [
"prettier --write"
],
"*.ts?(x)": [
"prettier --parser=typescript --write"
]
},
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"react",
"react-dom",
"antd",
"dva",
"postcss",
"webpack",
"eslint",
"stylelint",
"redux",
"@babel/core",
"monaco-editor",
"rc-field-form",
"@types/lodash.merge",
"rollup"
],
"allowedVersions": {
"react": "18",
"react-dom": "18",
"dva-core": "2"
}
}
},
"dependencies": {
"@otplib/preset-default": "^12.0.1",
"@sentry/node": "^7.12.1",
"@sentry/tracing": "^7.12.1",
"body-parser": "^1.19.2",
"celebrate": "^15.0.1",
"chokidar": "^3.5.3",
"cors": "^2.8.5",
"cron-parser": "^4.2.1",
"dayjs": "^1.11.2",
"dotenv": "^16.0.0",
"express": "^4.17.3",
"express-jwt": "^6.1.1",
"express-urlrewrite": "^1.4.0",
"form-data": "^4.0.0",
"got": "^11.8.2",
"hpagent": "^0.1.2",
"iconv-lite": "^0.6.3",
"js-yaml": "^4.1.0",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.21",
"multer": "^1.4.4",
"nedb": "^1.8.0",
"node-schedule": "^2.1.0",
"nodemailer": "^6.7.2",
"pstree.remy": "^1.1.8",
"reflect-metadata": "^0.1.13",
"sequelize": "^6.25.5",
"serve-handler": "^6.1.3",
"sockjs": "^0.3.24",
"sqlite3": "npm:@louislam/sqlite3@^15.0.6",
"toad-scheduler": "^1.6.0",
"typedi": "^0.10.0",
"uuid": "^8.3.2",
"winston": "^3.6.0",
"yargs": "^17.3.1"
},
"devDependencies": {
"@ant-design/icons": "^4.7.0",
"@ant-design/pro-layout": "^6.33.1",
"@monaco-editor/react": "4.4.6",
"@react-hook/resize-observer": "^1.2.6",
"@sentry/react": "^7.12.1",
"@types/body-parser": "^1.19.2",
"@types/cors": "^2.8.12",
"@types/express": "^4.17.13",
"@types/express-jwt": "^6.0.4",
"@types/js-yaml": "^4.0.5",
"@types/jsonwebtoken": "^8.5.8",
"@types/lodash": "^4.14.185",
"@types/multer": "^1.4.7",
"@types/nedb": "^1.8.12",
"@types/node": "^17.0.21",
"@types/node-schedule": "^1.3.2",
"@types/nodemailer": "^6.4.4",
"@types/qrcode.react": "^1.0.2",
"@types/react": "^18.0.20",
"@types/react-dom": "^18.0.6",
"@types/serve-handler": "^6.1.1",
"@types/sockjs": "^0.3.33",
"@types/sockjs-client": "^1.5.1",
"@types/uuid": "^8.3.4",
"@umijs/max": "^4.0.21",
"@umijs/ssr-darkreader": "^4.9.45",
"ansi-to-react": "^6.1.6",
"antd": "^4.23.0",
"antd-img-crop": "^4.2.3",
"codemirror": "^5.65.2",
"compression-webpack-plugin": "9.2.0",
"concurrently": "^7.0.0",
"lint-staged": "^13.0.3",
"monaco-editor": "^0.34.1",
"nodemon": "^2.0.15",
"prettier": "^2.5.1",
"qiniu": "^7.4.0",
"qrcode.react": "^1.0.1",
"query-string": "^7.1.1",
"rc-tween-one": "^3.0.6",
"react": "18.2.0",
"react-codemirror2": "^7.2.1",
"react-diff-viewer": "^3.1.1",
"react-dnd": "^14.0.2",
"react-dnd-html5-backend": "^14.0.0",
"react-dom": "18.2.0",
"react-split-pane": "^0.1.92",
"sockjs-client": "^1.6.0",
"ts-node": "^10.6.0",
"tslib": "^2.4.0",
"typescript": "4.8.4",
"umi-request": "^1.4.0",
"vh-check": "^2.0.5",
"webpack": "^5.70.0",
"yorkie": "^2.0.0"
}
}
@@ -28,8 +28,9 @@ export default (app: Router) => {
celebrate({
body: Joi.object({
name: Joi.string().required(),
sorts: Joi.array().optional(),
sorts: Joi.array().optional().allow(null),
filters: Joi.array().optional(),
filterRelation: Joi.string().optional(),
}),
}),
async (req: Request, res: Response, next: NextFunction) => {
@@ -49,15 +50,20 @@ export default (app: Router) => {
body: Joi.object({
name: Joi.string().required(),
id: Joi.number().required(),
sorts: Joi.array().optional(),
sorts: Joi.array().optional().allow(null),
filters: Joi.array().optional(),
filterRelation: Joi.string().optional(),
}),
}),
async (req: Request, res: Response, next: NextFunction) => {
try {
const cronViewService = Container.get(CronViewService);
const data = await cronViewService.update(req.body);
return res.send({ code: 200, data });
if (req.body.type === 1) {
return res.send({ code: 400, message: '参数错误' });
} else {
const data = await cronViewService.update(req.body);
return res.send({ code: 200, data });
}
} catch (e) {
return next(e);
}
@@ -3,8 +3,21 @@ import { Container } from 'typedi';
import EnvService from '../services/env';
import { Logger } from 'winston';
import { celebrate, Joi } from 'celebrate';
import multer from 'multer';
import config from '../config';
import fs from 'fs';
const route = Router();
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, config.scriptPath);
},
filename: function (req, file, cb) {
cb(null, file.originalname);
},
});
const upload = multer({ storage: storage });
export default (app: Router) => {
app.use('/envs', route);
@@ -26,7 +39,9 @@ export default (app: Router) => {
body: Joi.array().items(
Joi.object({
value: Joi.string().required(),
name: Joi.string().required(),
name: Joi.string()
.required()
.pattern(/^[a-zA-Z_][0-9a-zA-Z_]*$/),
remarks: Joi.string().optional().allow(''),
}),
),
@@ -94,7 +109,6 @@ export default (app: Router) => {
}),
}),
async (req: Request<{ id: number }>, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const envService = Container.get(EnvService);
const data = await envService.move(req.params.id, req.body);
@@ -177,4 +191,37 @@ export default (app: Router) => {
}
},
);
route.post(
'/upload',
upload.single('env'),
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const envService = Container.get(EnvService);
const fileContent = await fs.promises.readFile(req!.file!.path, 'utf8');
const parseContent = JSON.parse(fileContent);
const data = Array.isArray(parseContent)
? parseContent
: [parseContent];
if (data.every((x) => x.name && x.value)) {
const result = await envService.create(
data.map((x) => ({
name: x.name,
value: x.value,
remarks: x.remarks,
})),
);
return res.send({ code: 200, data: result });
} else {
return res.send({
code: 400,
message: '文件缺少name或者value字段,参考导出文件格式',
});
}
} catch (e) {
return next(e);
}
},
);
};
@@ -3,8 +3,9 @@ import { Container } from 'typedi';
import { Logger } from 'winston';
import * as fs from 'fs';
import config from '../config';
import { getFileContentByName, readDirs } from '../config/util';
import { emptyDir, getFileContentByName, readDirs } from '../config/util';
import { join } from 'path';
import { celebrate, Joi } from 'celebrate';
const route = Router();
const blacklist = ['.tmp'];
@@ -45,4 +46,33 @@ export default (app: Router) => {
}
},
);
route.delete(
'/',
celebrate({
body: Joi.object({
filename: Joi.string().required(),
path: Joi.string().allow(''),
type: Joi.string().optional(),
}),
}),
async (req: Request, res: Response, next: NextFunction) => {
try {
let { filename, path, type } = req.body as {
filename: string;
path: string;
type: string;
};
const filePath = join(config.logPath, path, filename);
if (type === 'directory') {
emptyDir(filePath);
} else {
fs.unlinkSync(filePath);
}
res.send({ code: 200 });
} catch (e) {
return next(e);
}
},
);
};
@@ -4,6 +4,7 @@ import {
readDirs,
getLastModifyFilePath,
readDir,
emptyDir,
} from '../config/util';
import { Router, Request, Response, NextFunction } from 'express';
import { Container } from 'typedi';
@@ -77,12 +78,14 @@ export default (app: Router) => {
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
let { filename, path, content, originFilename } = req.body as {
filename: string;
path: string;
content: string;
originFilename: string;
};
let { filename, path, content, originFilename, directory } =
req.body as {
filename: string;
path: string;
content: string;
originFilename: string;
directory: string;
};
if (!path) {
path = config.scriptPath;
@@ -105,11 +108,19 @@ export default (app: Router) => {
return res.send({ code: 200 });
}
if (directory) {
fs.mkdirSync(join(path, directory), { recursive: true });
return res.send({ code: 200 });
}
if (!originFilename) {
originFilename = filename;
}
const originFilePath = `${path}${originFilename.replace(/\//g, '')}`;
const filePath = `${path}${filename.replace(/\//g, '')}`;
const originFilePath = join(
path,
`${originFilename.replace(/\//g, '')}`,
);
const filePath = join(path, `${filename.replace(/\//g, '')}`);
if (fs.existsSync(originFilePath)) {
fs.copyFileSync(
originFilePath,
@@ -159,17 +170,23 @@ export default (app: Router) => {
body: Joi.object({
filename: Joi.string().required(),
path: Joi.string().allow(''),
type: Joi.string().optional(),
}),
}),
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
let { filename, path } = req.body as {
let { filename, path, type } = req.body as {
filename: string;
path: string;
type: string;
};
const filePath = join(config.scriptPath, path, filename);
fs.unlinkSync(filePath);
if (type === 'directory') {
emptyDir(filePath);
} else {
fs.unlinkSync(filePath);
}
res.send({ code: 200 });
} catch (e) {
return next(e);
@@ -238,23 +255,50 @@ export default (app: Router) => {
celebrate({
body: Joi.object({
filename: Joi.string().required(),
content: Joi.string().optional().allow(''),
path: Joi.string().optional().allow(''),
pid: Joi.number().optional().allow(''),
}),
}),
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
let { filename, content, path } = req.body;
let { filename, path, pid } = req.body;
const { name, ext } = parse(filename);
const filePath = join(config.scriptPath, path, `${name}.swap${ext}`);
const scriptService = Container.get(ScriptService);
const result = await scriptService.stopScript(filePath);
const result = await scriptService.stopScript(filePath, pid);
res.send(result);
} catch (e) {
return next(e);
}
},
);
route.put(
'/rename',
celebrate({
body: Joi.object({
filename: Joi.string().required(),
path: Joi.string().allow(''),
newFilename: Joi.string().required(),
}),
}),
async (req: Request, res: Response, next: NextFunction) => {
try {
let { filename, path, type, newFilename } = req.body as {
filename: string;
path: string;
type: string;
newFilename: string;
};
const filePath = join(config.scriptPath, path, filename);
const newPath = join(config.scriptPath, path, newFilename);
fs.renameSync(filePath, newPath);
res.send({ code: 200 });
} catch (e) {
return next(e);
}
},
);
};
@@ -49,6 +49,7 @@ export default (app: Router) => {
sub_after: Joi.string().optional().allow('').allow(null),
schedule_type: Joi.string().required(),
alias: Joi.string().required(),
proxy: Joi.string().optional().allow('').allow(null),
}),
}),
async (req: Request, res: Response, next: NextFunction) => {
@@ -177,6 +178,7 @@ export default (app: Router) => {
sub_before: Joi.string().optional().allow('').allow(null),
sub_after: Joi.string().optional().allow('').allow(null),
alias: Joi.string().required(),
proxy: Joi.string().optional().allow('').allow(null),
id: Joi.number().required(),
}),
}),
@@ -7,6 +7,9 @@ import SystemService from '../services/system';
import { celebrate, Joi } from 'celebrate';
import UserService from '../services/user';
import { EnvModel } from '../data/env';
import { parseVersion, promiseExec } from '../config/util';
import dayjs from 'dayjs';
const route = Router();
export default (app: Router) => {
@@ -18,10 +21,22 @@ export default (app: Router) => {
const userService = Container.get(UserService);
const authInfo = await userService.getUserInfo();
const envCount = await EnvModel.count();
const versionRegx = /.*export const version = \'(.*)\'\;/;
const currentVersionFile = fs.readFileSync(config.versionFile, 'utf8');
const version = currentVersionFile.match(versionRegx)![1];
const { version, changeLog, changeLogLink } = await parseVersion(
config.versionFile,
);
const lastCommitTime = (
await promiseExec(
`cd ${config.rootPath} && git show -s --format=%ai | head -1`,
)
).replace('\n', '');
const lastCommitId = (
await promiseExec(`cd ${config.rootPath} && git rev-parse --short HEAD`)
).replace('\n', '');
const branch = (
await promiseExec(
`cd ${config.rootPath} && git symbolic-ref --short HEAD`,
)
).replace('\n', '');
let isInitialized = true;
if (
@@ -37,6 +52,11 @@ export default (app: Router) => {
data: {
isInitialized,
version,
lastCommitTime: dayjs(lastCommitTime).unix(),
lastCommitId,
branch,
changeLog,
changeLogLink,
},
});
} catch (e) {
+1 -1
View File
@@ -17,7 +17,7 @@ async function startServer() {
const server = app
.listen(config.port, () => {
Logger.debug(`✌️ Back server launched on port ${config.port}`);
Logger.debug(`✌️ 后端服务启动成功!`);
})
.on('error', (err) => {
Logger.error(err);
+1
View File
@@ -0,0 +1 @@
export const LOG_END_SYMBOL = '\n          ';
@@ -6,15 +6,15 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development';
if (!process.env.QL_DIR) {
// 声明QL_DIR环境变量
let qlHomePath = path.join(__dirname, '../../');
let qlHomePath = path.join(__dirname, '../../../../');
// 生产环境
if (qlHomePath.endsWith('/static/')) {
qlHomePath = path.join(qlHomePath, '../');
}
process.env.QL_DIR = qlHomePath;
process.env.QL_DIR = qlHomePath.replace(/\/$/g, '');
}
const lastVersionFile = `http://qn.whyour.cn/version.ts?v=${Date.now()}`;
const lastVersionFile = `https://qn.whyour.cn/version.yaml`;
const rootPath = process.env.QL_DIR as string;
const envFound = dotenv.config({ path: path.join(rootPath, '.env') });
@@ -40,7 +40,7 @@ const sqliteFile = path.join(samplePath, 'database.sqlite');
const authError = '错误的用户名密码,请重试';
const loginFaild = '请先登录!';
const configString = 'config sample crontab shareCode diy';
const versionFile = path.join(rootPath, 'src/version.ts');
const versionFile = path.join(rootPath, 'version.yaml');
if (envFound.error) {
throw new Error("⚠️ Couldn't find .env file ⚠️");
@@ -3,6 +3,10 @@ import * as path from 'path';
import got from 'got';
import iconv from 'iconv-lite';
import { exec } from 'child_process';
import FormData from 'form-data';
import psTreeFun from 'pstree.remy';
import { promisify } from 'util';
import { load } from 'js-yaml';
export function getFileContentByName(fileName: string) {
if (fs.existsSync(fileName)) {
@@ -283,6 +287,20 @@ enum FileType {
'file',
}
interface IFile {
title: string;
key: string;
type: 'directory' | 'file';
parent: string;
mtime: number;
children?: IFile[];
}
export function dirSort(a: IFile, b: IFile) {
if (a.type !== b.type) return FileType[a.type] < FileType[b.type] ? -1 : 1;
else if (a.mtime !== b.mtime) return a.mtime > b.mtime ? -1 : 1;
}
export function readDirs(
dir: string,
baseDir: string = '',
@@ -301,24 +319,21 @@ export function readDirs(
title: file,
key,
type: 'directory',
disabled: true,
parent: relativePath,
children: readDirs(subPath, baseDir).sort(
(a: any, b: any) =>
(FileType as any)[a.type] - (FileType as any)[b.type],
),
mtime: stats.mtime.getTime(),
children: readDirs(subPath, baseDir).sort(dirSort),
};
}
return {
title: file,
type: 'file',
isLeaf: true,
key,
parent: relativePath,
mtime: stats.mtime.getTime(),
};
});
return result.sort(
(a: any, b: any) => (FileType as any)[a.type] - (FileType as any)[b.type],
);
return result.sort(dirSort);
}
export function readDir(
@@ -344,6 +359,20 @@ export function readDir(
return result;
}
export function emptyDir(path: string) {
const files = fs.readdirSync(path);
files.forEach((file) => {
const filePath = `${path}/${file}`;
const stats = fs.statSync(filePath);
if (stats.isDirectory()) {
emptyDir(filePath);
} else {
fs.unlinkSync(filePath);
}
});
fs.rmdirSync(path);
}
export function promiseExec(command: string): Promise<string> {
return new Promise((resolve, reject) => {
exec(
@@ -355,3 +384,116 @@ export function promiseExec(command: string): Promise<string> {
);
});
}
export function parseHeaders(headers: string) {
if (!headers) return {};
const parsed: any = {};
let key;
let val;
let i;
headers &&
headers.split('\n').forEach(function parser(line) {
i = line.indexOf(':');
key = line.substring(0, i).trim().toLowerCase();
val = line.substring(i + 1).trim();
if (!key) {
return;
}
parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
});
return parsed;
}
export function parseBody(
body: string,
contentType:
| 'application/json'
| 'multipart/form-data'
| 'application/x-www-form-urlencoded',
) {
if (!body) return '';
const parsed: any = {};
let key;
let val;
let i;
body &&
body.split('\n').forEach(function parser(line) {
i = line.indexOf(':');
key = line.substring(0, i).trim().toLowerCase();
val = line.substring(i + 1).trim();
if (!key || parsed[key]) {
return;
}
try {
const jsonValue = JSON.parse(val);
parsed[key] = jsonValue;
} catch (error) {
parsed[key] = val;
}
});
switch (contentType) {
case 'multipart/form-data':
return Object.keys(parsed).reduce((p, c) => {
p.append(c, parsed[c]);
return p;
}, new FormData());
case 'application/x-www-form-urlencoded':
return Object.keys(parsed).reduce((p, c) => {
return p ? `${p}&${c}=${parsed[c]}` : `${c}=${parsed[c]}`;
});
}
return parsed;
}
export function psTree(pid: number): Promise<number[]> {
return new Promise((resolve, reject) => {
psTreeFun(pid, (err: any, pids: number[]) => {
if (err) {
reject(err);
}
resolve(pids.filter((x) => !isNaN(x)));
});
});
}
export async function killTask(pid: number) {
const pids = await psTree(pid);
// SIGALRM 14 时钟信号
if (pids.length) {
process.kill(pids[0], 14);
} else {
process.kill(pid, 14);
}
}
export async function getPid(name: string) {
let taskCommand = `ps -ef | grep "${name}" | grep -v grep | awk '{print $1}'`;
const execAsync = promisify(exec);
let pid = (await execAsync(taskCommand)).stdout;
return Number(pid);
}
interface IVersion {
version: string;
changeLogLink: string;
changeLog: string;
}
export async function parseVersion(path: string): Promise<IVersion> {
return load(await promisify(fs.readFile)(path, 'utf8')) as IVersion;
}
export async function parseContentVersion(content: string): Promise<IVersion> {
return load(content) as IVersion;
}
@@ -1,13 +1,19 @@
import { sequelize } from '.';
import { DataTypes, Model } from 'sequelize';
export enum CronViewType {
'系统' = 1,
'个人',
}
interface SortType {
type: 'ASC' | 'DESC';
value: string;
}
interface FilterType {
type: 'or' | 'and';
property: string;
operation: string;
value: string;
}
@@ -18,6 +24,8 @@ export class CrontabView {
isDisabled?: 1 | 0;
filters?: FilterType[];
sorts?: SortType[];
filterRelation?: 'and' | 'or';
type?: CronViewType;
constructor(options: CrontabView) {
this.name = options.name;
@@ -26,6 +34,8 @@ export class CrontabView {
this.isDisabled = options.isDisabled || 0;
this.filters = options.filters;
this.sorts = options.sorts;
this.filterRelation = options.filterRelation;
this.type = options.type || CronViewType.;
}
}
@@ -43,5 +53,10 @@ export const CrontabViewModel = sequelize.define<CronViewInstance>(
isDisabled: DataTypes.NUMBER,
filters: DataTypes.JSON,
sorts: DataTypes.JSON,
filterRelation: {
type: DataTypes.STRING,
allowNull: true,
},
type: DataTypes.NUMBER,
},
);
@@ -26,7 +26,10 @@ export enum EnvStatus {
'disabled',
}
export const initEnvPosition = 9999999999;
export const maxPosition = 9000000000000000;
export const initPosition = 4500000000000000;
export const stepPosition = 10000000;
export const minPosition = 100;
interface EnvInstance extends Model<Env, Env>, Env {}
export const EnvModel = sequelize.define<EnvInstance>('Env', {
@@ -1,15 +1,22 @@
import { Sequelize } from 'sequelize';
import { Sequelize, Transaction } from 'sequelize';
import config from '../config/index';
export const sequelize = new Sequelize({
dialect: 'sqlite',
storage: `${config.dbPath}database.sqlite`,
logging: false,
pool: {
max: 6,
min: 0,
idle: 30000,
retry: {
max: 10,
match: ['SQLITE_BUSY: database is locked'],
},
pool: {
max: 5,
min: 2,
idle: 30000,
acquire: 30000,
evict: 10000,
},
transactionType: Transaction.TYPES.IMMEDIATE,
});
export type ResponseType<T> = { code: number; data?: T; message?: string };
@@ -1,3 +1,5 @@
import { IncomingHttpHeaders } from 'http';
export enum NotificationMode {
'gotify' = 'gotify',
'goCqHttpBot' = 'goCqHttpBot',
@@ -9,9 +11,12 @@ export enum NotificationMode {
'dingtalkBot' = 'dingtalkBot',
'weWorkBot' = 'weWorkBot',
'weWorkApp' = 'weWorkApp',
'aibotk' = 'aibotk',
'iGot' = 'iGot',
'pushPlus' = 'pushPlus',
'email' = 'email',
'feishu' = 'feishu',
'webhook' = 'webhook',
}
abstract class NotificationBaseInfo {
@@ -36,6 +41,7 @@ export class ServerChanNotification extends NotificationBaseInfo {
export class PushDeerNotification extends NotificationBaseInfo {
public pushDeerKey = '';
public pushDeerUrl = '';
}
export class ChatNotification extends NotificationBaseInfo {
@@ -45,7 +51,7 @@ export class ChatNotification extends NotificationBaseInfo {
export class BarkNotification extends NotificationBaseInfo {
public barkPush = '';
public barkIcon = 'http://qn.whyour.cn/logo.png';
public barkIcon = 'https://qn.whyour.cn/logo.png';
public barkSound = '';
public barkGroup = 'qinglong';
}
@@ -72,6 +78,12 @@ export class WeWorkAppNotification extends NotificationBaseInfo {
public weWorkAppKey = '';
}
export class AibotkNotification extends NotificationBaseInfo {
public aibotkKey: string = '';
public aibotkType: 'room' | 'contact' = 'room';
public aibotkName: string = '';
}
export class IGotNotification extends NotificationBaseInfo {
public iGotPushKey = '';
}
@@ -87,6 +99,21 @@ export class EmailNotification extends NotificationBaseInfo {
public emailPass: string = '';
}
export class WebhookNotification extends NotificationBaseInfo {
public webhookHeaders: string = '';
public webhookBody: string = '';
public webhookUrl: string = '';
public webhookMethod: 'GET' | 'POST' | 'PUT' = 'GET';
public webhookContentType:
| 'application/json'
| 'multipart/form-data'
| 'application/x-www-form-urlencoded' = 'application/json';
}
export class LarkNotification extends NotificationBaseInfo {
public larkKey = '';
}
export interface NotificationInfo
extends GoCqHttpBotNotification,
GotifyNotification,
@@ -98,6 +125,9 @@ export interface NotificationInfo
DingtalkBotNotification,
WeWorkBotNotification,
WeWorkAppNotification,
AibotkNotification,
IGotNotification,
PushPlusNotification,
EmailNotification {}
EmailNotification,
WebhookNotification,
LarkNotification {}
@@ -28,6 +28,7 @@ export class Subscription {
extensions?: string;
sub_before?: string;
sub_after?: string;
proxy?: string;
constructor(options: Subscription) {
this.id = options.id;
@@ -54,6 +55,7 @@ export class Subscription {
this.extensions = options.extensions;
this.sub_before = options.sub_before;
this.sub_after = options.sub_after;
this.proxy = options.proxy;
}
}
@@ -102,5 +104,6 @@ export const SubscriptionModel = sequelize.define<SubscriptionInstance>(
log_path: DataTypes.STRING,
schedule_type: DataTypes.STRING,
alias: { type: DataTypes.STRING, unique: 'alias' },
proxy: { type: DataTypes.STRING, allowNull: true },
},
);
View File
@@ -10,6 +10,7 @@ import { fileExist } from '../config/util';
import { SubscriptionModel } from '../data/subscription';
import { CrontabViewModel } from '../data/cronView';
import config from '../config';
import { sequelize } from '../data';
export default async () => {
try {
@@ -21,12 +22,20 @@ export default async () => {
await SubscriptionModel.sync();
await CrontabViewModel.sync();
// try {
// const queryInterface = sequelize.getQueryInterface();
// await queryInterface.addIndex('Crontabs', ['command'], { unique: true });
// await queryInterface.addIndex('Envs', ['name', 'value'], { unique: true });
// await queryInterface.addIndex('Apps', ['name'], { unique: true });
// } catch (error) { }
// 初始化新增字段
try {
await sequelize.query(
'alter table CrontabViews add column filterRelation VARCHAR(255)',
);
} catch (error) {}
try {
await sequelize.query(
'alter table Subscriptions add column proxy VARCHAR(255)',
);
} catch (error) {}
try {
await sequelize.query('alter table CrontabViews add column type NUMBER');
} catch (error) {}
// 2.10-2.11 升级
const cronDbFile = path.join(config.rootPath, 'db/crontab.db');
@@ -3,7 +3,7 @@ import bodyParser from 'body-parser';
import cors from 'cors';
import routes from '../api';
import config from '../config';
import jwt from 'express-jwt';
import jwt, { UnauthorizedError } from 'express-jwt';
import fs from 'fs';
import { getPlatform, getToken } from '../config/util';
import Container from 'typedi';
@@ -75,22 +75,24 @@ export default ({ app }: { app: Application }) => {
if (
!headerToken &&
originPath &&
config.apiWhiteList.includes(originPath) &&
originPath !== '/api/crons/status'
config.apiWhiteList.includes(originPath)
) {
return next();
}
const data = fs.readFileSync(config.authConfigFile, 'utf8');
if (data) {
if (data && headerToken) {
const { token = '', tokens = {} } = JSON.parse(data);
if (headerToken === token || tokens[req.platform] === headerToken) {
return next();
}
}
const err: any = new Error('UnauthorizedError');
err.status = 401;
const errorCode = headerToken ? 'invalid_token' : 'credentials_required';
const errorMessage = headerToken
? 'jwt malformed'
: 'No authorization token was found';
const err = new UnauthorizedError(errorCode, { message: errorMessage });
next(err);
});
@@ -168,7 +170,17 @@ export default ({ app }: { app: Application }) => {
},
);
app.use(Sentry.Handlers.errorHandler());
app.use(
Sentry.Handlers.errorHandler({
shouldHandleError(error) {
// 排除 SequelizeUniqueConstraintError / NotFound
return (
!['SequelizeUniqueConstraintError'].includes(error.name) ||
!['Not Found'].includes(error.message)
);
},
}),
);
app.use(
(
@@ -4,16 +4,32 @@ import { Container } from 'typedi';
import { Crontab, CrontabModel, CrontabStatus } from '../data/cron';
import CronService from '../services/cron';
import EnvService from '../services/env';
import _ from 'lodash';
import groupBy from 'lodash/groupBy';
import { DependenceModel } from '../data/dependence';
import { Op } from 'sequelize';
import config from '../config';
import { CrontabViewModel, CronViewType } from '../data/cronView';
import { initPosition } from '../data/env';
export default async () => {
const cronService = Container.get(CronService);
const envService = Container.get(EnvService);
const dependenceService = Container.get(DependenceService);
// 初始化新增默认全部任务视图
CrontabViewModel.findAll({
where: { type: CronViewType., name: '全部任务' },
raw: true,
}).then((docs) => {
if (docs.length === 0) {
CrontabViewModel.create({
name: '全部任务',
type: CronViewType.,
position: initPosition / 2,
});
}
});
// 初始化更新所有任务状态为空闲
await CrontabModel.update(
{ status: CrontabStatus.idle },
@@ -26,7 +42,7 @@ export default async () => {
order: [['type', 'DESC']],
raw: true,
}).then(async (docs) => {
const groups = _.groupBy(docs, 'type');
const groups = groupBy(docs, 'type');
const keys = Object.keys(groups).sort((a, b) => parseInt(b) - parseInt(a));
for (const key of keys) {
const group = groups[key];
@@ -4,8 +4,7 @@ import os from 'os';
import dotenv from 'dotenv';
import Logger from './logger';
import { fileExist } from '../config/util';
const rootPath = process.env.QL_DIR as string;;
const rootPath = process.env.QL_DIR as string;
const dataPath = path.join(rootPath, 'data/');
const configPath = path.join(dataPath, 'config/');
const scriptPath = path.join(dataPath, 'scripts/');
@@ -1,5 +1,4 @@
import { Container } from 'typedi';
import _ from 'lodash';
import SystemService from '../services/system';
import ScheduleService from '../services/schedule';
import SubscriptionService from '../services/subscription';
@@ -13,18 +12,17 @@ export default async () => {
// 生成内置token
let tokenCommand = `ts-node-transpile-only ${config.rootPath}/back/token.ts`;
const tokenFile = `${config.rootPath}/static/build/token.js`;
const tokenFile = `${config.rootPath}static/build/token.js`;
if (await fileExist(tokenFile)) {
tokenCommand = `node ${tokenFile}`;
}
const cron = {
id: 'token',
id: NaN,
name: '生成token',
command: tokenCommand,
};
scheduleService.createIntervalTask(cron as any, {
scheduleService.createIntervalTask(cron, {
days: 28,
runImmediately: true,
});
// 运行删除日志任务
@@ -37,7 +35,6 @@ export default async () => {
};
scheduleService.createIntervalTask(cron, {
days: data.info.frequency,
runImmediately: true,
});
}
@@ -2,16 +2,21 @@ import { Application } from 'express';
import * as Sentry from '@sentry/node';
import * as Tracing from '@sentry/tracing';
import Logger from './logger';
import config from '../config';
import fs from 'fs';
import { parseVersion } from '../config/util';
export default async ({ expressApp }: { expressApp: Application }) => {
const { version } = await parseVersion(config.versionFile);
export default ({ expressApp }: { expressApp: Application }) => {
Sentry.init({
dsn: 'https://f4b5b55fb3c645b29a5dc2d70a1a4ef4@o1098464.ingest.sentry.io/6122819',
integrations: [
new Sentry.Integrations.Http({ tracing: true }),
new Tracing.Integrations.Express({ app: expressApp }),
],
tracesSampleRate: 1.0,
tracesSampleRate: 0.1,
release: version,
});
expressApp.use(Sentry.Handlers.requestHandler());
@@ -5,12 +5,15 @@ import { Crontab, CrontabModel, CrontabStatus } from '../data/cron';
import { exec, execSync, spawn } from 'child_process';
import fs from 'fs';
import cron_parser from 'cron-parser';
import { getFileContentByName, concurrentRun, fileExist } from '../config/util';
import {
getFileContentByName,
concurrentRun,
fileExist,
killTask,
} from '../config/util';
import { promises, existsSync } from 'fs';
import { promisify } from 'util';
import { Op } from 'sequelize';
import { Op, where, col as colFn } from 'sequelize';
import path from 'path';
import dayjs from 'dayjs';
@Service()
export default class CronService {
@@ -115,18 +118,26 @@ export default class CronService {
private formatViewQuery(query: any, viewQuery: any) {
if (viewQuery.filters && viewQuery.filters.length > 0) {
const primaryOperate = viewQuery.filterRelation === 'or' ? Op.or : Op.and;
if (!query[primaryOperate]) {
query[primaryOperate] = [];
}
for (const col of viewQuery.filters) {
const { property, value, operation } = col;
let q: any = {};
let operate2 = null;
let operate = null;
switch (operation) {
case 'Reg':
operate = Op.like;
operate2 = Op.or;
break;
case 'NotReg':
operate = Op.notLike;
operate2 = Op.and;
break;
case 'In':
query[Op.or] = [
q[Op.or] = [
{
[property]: value,
},
@@ -136,7 +147,7 @@ export default class CronService {
];
break;
case 'Nin':
query[Op.and] = [
q[Op.and] = [
{
[property]: {
[Op.notIn]: value,
@@ -150,20 +161,39 @@ export default class CronService {
default:
break;
}
if (operate) {
query[property] = {
if (operate && operate2) {
q[property] = {
[Op.or]: [
{ [operate]: `%${value}%` },
{ [operate]: `%${encodeURIComponent(value)}%` },
{
[operate2]: [
{ [operate]: `%${value}%` },
{ [operate]: `%${encodeURIComponent(value)}%` },
],
},
{
[operate2]: [
where(colFn(property), operate, `%${value}%`),
where(
colFn(property),
operate,
`%${encodeURIComponent(value)}%`,
),
],
},
],
};
}
query[primaryOperate].push(q);
}
}
}
private formatSearchText(query: any, searchText: string | undefined) {
if (searchText) {
if (!query[Op.and]) {
query[Op.and] = [];
}
let q: any = {};
const textArray = searchText.split(':');
switch (textArray[0]) {
case 'name':
@@ -171,7 +201,7 @@ export default class CronService {
case 'schedule':
case 'label':
const column = textArray[0] === 'label' ? 'labels' : textArray[0];
query[column] = {
q[column] = {
[Op.or]: [
{ [Op.like]: `%${textArray[1]}%` },
{ [Op.like]: `%${encodeURIComponent(textArray[1])}%` },
@@ -185,7 +215,7 @@ export default class CronService {
{ [Op.like]: `%${encodeURIComponent(searchText)}%` },
],
};
query[Op.or] = [
q[Op.or] = [
{
name: reg,
},
@@ -201,6 +231,23 @@ export default class CronService {
];
break;
}
query[Op.and].push(q);
}
}
private formatFilterQuery(query: any, filterQuery: any) {
if (filterQuery) {
if (!query[Op.and]) {
query[Op.and] = [];
}
const filterKeys: any = Object.keys(filterQuery);
for (const key of filterKeys) {
let q: any = {};
if (filterKeys[key]) {
q[key] = filterKeys[key];
}
query[Op.and].push(q);
}
}
}
@@ -216,16 +263,16 @@ export default class CronService {
searchValue: string;
page: string;
size: string;
sortField: string;
sortType: string;
sorter: string;
filters: string;
queryString: string;
}): Promise<{ data: Crontab[]; total: number }> {
const searchText = params?.searchValue;
const page = Number(params?.page || '0');
const size = Number(params?.size || '0');
const sortField = params?.sortField || '';
const sortType = params?.sortType || '';
const viewQuery = JSON.parse(params?.queryString || '{}');
const filterQuery = JSON.parse(params?.filters || '{}');
const sorterQuery = JSON.parse(params?.sorter || '{}');
let query: any = {};
let order = [
@@ -237,10 +284,14 @@ export default class CronService {
this.formatViewQuery(query, viewQuery);
this.formatSearchText(query, searchText);
this.formatFilterQuery(query, filterQuery);
this.formatViewSort(order, viewQuery);
if (sortType && sortField) {
order.unshift([sortField, sortType]);
if (sorterQuery) {
const { field, type } = sorterQuery;
if (field && type) {
order.unshift([field, type]);
}
}
let condition: any = {
where: query,
@@ -280,31 +331,11 @@ export default class CronService {
for (const doc of docs) {
if (doc.pid) {
try {
process.kill(-doc.pid);
await killTask(doc.pid);
} catch (error) {
this.logger.silly(error);
}
}
const err = await this.killTask(doc.command);
const absolutePath = path.resolve(config.logPath, `${doc.log_path}`);
const logFileExist = doc.log_path && (await fileExist(absolutePath));
const endTime = dayjs();
const diffTimeStr = doc.last_execution_time
? `,耗时 ${endTime.diff(
dayjs(doc.last_execution_time * 1000),
'second',
)}`
: '';
if (logFileExist) {
const str = err ? `\n${err}` : '';
fs.appendFileSync(
`${absolutePath}`,
`${str}\n## 执行结束... ${endTime.format(
'YYYY-MM-DD HH:mm:ss',
)}${diffTimeStr}`,
);
}
}
await CrontabModel.update(
@@ -313,42 +344,6 @@ export default class CronService {
);
}
public async killTask(name: string) {
let taskCommand = `ps -ef | grep "${name}" | grep -v grep | awk '{print $1}'`;
const execAsync = promisify(exec);
try {
let pid = (await execAsync(taskCommand)).stdout;
if (pid) {
pid = (await execAsync(`pstree -p ${pid}`)).stdout;
} else {
return;
}
let pids = pid.match(/\(\d+/g);
const killLogs = [];
if (pids && pids.length > 0) {
// node 执行脚本时还会有10个子进程,但是ps -ef中不存在,所以截取前三个
pids = pids.slice(0, 3);
for (const id of pids) {
const c = `kill -9 ${id.slice(1)}`;
try {
const { stdout, stderr } = await execAsync(c);
if (stderr) {
killLogs.push(stderr);
}
if (stdout) {
killLogs.push(stdout);
}
} catch (error: any) {
killLogs.push(error.message);
}
}
}
return killLogs.length > 0 ? JSON.stringify(killLogs) : '';
} catch (e) {
return JSON.stringify(e);
}
}
private async runSingle(cronId: number): Promise<number> {
return new Promise(async (resolve: any) => {
const cron = await this.getDb({ id: cronId });
@@ -379,7 +374,7 @@ export default class CronService {
cmdStr = `${cmdStr} now`;
}
const cp = spawn(cmdStr, { shell: '/bin/bash' });
const cp = spawn(`ID=${id} ${cmdStr}`, { shell: '/bin/bash' });
await CrontabModel.update(
{ status: CrontabStatus.running, pid: cp.pid },
@@ -387,7 +382,7 @@ export default class CronService {
);
cp.stderr.on('data', (data) => {
if (logFileExist) {
fs.appendFileSync(`${absolutePath}`, `${data}`);
fs.appendFileSync(`${absolutePath}`, `${data.toString()}`);
}
});
cp.on('error', (err) => {
@@ -1,14 +1,19 @@
import { Service, Inject } from 'typedi';
import winston from 'winston';
import { CrontabView, CrontabViewModel } from '../data/cronView';
import { initEnvPosition } from '../data/env';
import {
initPosition,
maxPosition,
minPosition,
stepPosition,
} from '../data/env';
@Service()
export default class CronViewService {
constructor(@Inject('logger') private logger: winston.Logger) {}
public async create(payload: CrontabView): Promise<CrontabView> {
let position = initEnvPosition;
let position = initPosition;
const views = await this.list();
if (views && views.length > 0 && views[views.length - 1].position) {
position = views[views.length - 1].position as number;
@@ -16,6 +21,8 @@ export default class CronViewService {
position = position / 2;
const tab = new CrontabView({ ...payload, position });
const doc = await this.insert(tab);
await this.checkPosition(tab.position!);
return doc;
}
@@ -62,6 +69,22 @@ export default class CronViewService {
await CrontabViewModel.update({ isDisabled: 0 }, { where: { id: ids } });
}
private async checkPosition(position: number) {
const precisionPosition = parseFloat(position.toPrecision(16));
if (precisionPosition < minPosition || precisionPosition > maxPosition) {
const envs = await this.list();
let position = initPosition;
for (const env of envs) {
position = position - stepPosition;
await this.updateDb({ id: env.id, position });
}
}
}
private getPrecisionPosition(position: number): number {
return parseFloat(position.toPrecision(16));
}
public async move({
id,
fromIndex,
@@ -76,17 +99,19 @@ export default class CronViewService {
const views = await this.list();
if (toIndex === 0 || toIndex === views.length - 1) {
targetPosition = isUpward
? views[0].position * 2
: views[toIndex].position / 2;
? views[0].position! * 2
: views[toIndex].position! / 2;
} else {
targetPosition = isUpward
? (views[toIndex].position + views[toIndex - 1].position) / 2
: (views[toIndex].position + views[toIndex + 1].position) / 2;
? (views[toIndex].position! + views[toIndex - 1].position!) / 2
: (views[toIndex].position! + views[toIndex + 1].position!) / 2;
}
const newDoc = await this.update({
id,
position: targetPosition,
position: this.getPrecisionPosition(targetPosition),
});
await this.checkPosition(targetPosition);
return newDoc;
}
}
@@ -9,7 +9,6 @@ import {
unInstallDependenceCommandTypes,
DependenceModel,
} from '../data/dependence';
import _ from 'lodash';
import { spawn } from 'child_process';
import SockService from './sock';
import { Op } from 'sequelize';
@@ -125,8 +124,11 @@ export default class DependenceService {
return docs;
}
private async find(query: any, sort?: any): Promise<Dependence[]> {
const docs = await DependenceModel.findAll({ where: { ...query } });
private async find(query: any, sort: any = []): Promise<Dependence[]> {
const docs = await DependenceModel.findAll({
where: { ...query },
order: [...sort, ['createdAt', 'DESC']],
});
return docs;
}
@@ -1,10 +1,17 @@
import { Service, Inject } from 'typedi';
import winston from 'winston';
import { getFileContentByName } from '../config/util';
import config from '../config';
import * as fs from 'fs';
import { Env, EnvModel, EnvStatus, initEnvPosition } from '../data/env';
import _ from 'lodash';
import {
Env,
EnvModel,
EnvStatus,
initPosition,
maxPosition,
minPosition,
stepPosition,
} from '../data/env';
import groupBy from 'lodash/groupBy';
import { Op } from 'sequelize';
@Service()
@@ -13,17 +20,22 @@ export default class EnvService {
public async create(payloads: Env[]): Promise<Env[]> {
const envs = await this.envs();
let position = initEnvPosition;
if (envs && envs.length > 0 && envs[envs.length - 1].position) {
position = envs[envs.length - 1].position as number;
let position = initPosition;
if (
envs &&
envs.length > 0 &&
typeof envs[envs.length - 1].position === 'number'
) {
position = envs[envs.length - 1].position!;
}
const tabs = payloads.map((x) => {
position = position / 2;
position = position - stepPosition;
const tab = new Env({ ...x, position });
return tab;
});
const docs = await this.insert(tabs);
await this.set_envs();
await this.checkPosition(tabs[tabs.length - 1].position!);
return docs;
}
@@ -67,25 +79,40 @@ export default class EnvService {
const envs = await this.envs();
if (toIndex === 0 || toIndex === envs.length - 1) {
targetPosition = isUpward
? envs[0].position * 2
: envs[toIndex].position / 2;
? envs[0].position! + stepPosition
: envs[toIndex].position! - stepPosition;
} else {
targetPosition = isUpward
? (envs[toIndex].position + envs[toIndex - 1].position) / 2
: (envs[toIndex].position + envs[toIndex + 1].position) / 2;
? (envs[toIndex].position! + envs[toIndex - 1].position!) / 2
: (envs[toIndex].position! + envs[toIndex + 1].position!) / 2;
}
const newDoc = await this.update({
id,
position: targetPosition,
position: this.getPrecisionPosition(targetPosition),
});
await this.checkPosition(targetPosition);
return newDoc;
}
public async envs(
searchText: string = '',
sort: any = { position: -1 },
query: any = {},
): Promise<Env[]> {
private async checkPosition(position: number) {
const precisionPosition = parseFloat(position.toPrecision(16));
if (precisionPosition < minPosition || precisionPosition > maxPosition) {
const envs = await this.envs();
let position = initPosition;
for (const env of envs) {
position = position - stepPosition;
await this.updateDb({ id: env.id, position });
}
}
}
private getPrecisionPosition(position: number): number {
return parseFloat(position.toPrecision(16));
}
public async envs(searchText: string = '', query: any = {}): Promise<Env[]> {
let condition = { ...query };
if (searchText) {
const encodeText = encodeURIComponent(searchText);
@@ -112,7 +139,11 @@ export default class EnvService {
};
}
try {
const result = await this.find(condition, [['position', 'DESC']]);
const result = await this.find(condition, [
['status', 'ASC'],
['position', 'DESC'],
['createdAt', 'ASC'],
]);
return result as any;
} catch (error) {
throw error;
@@ -151,22 +182,20 @@ export default class EnvService {
}
public async set_envs() {
const envs = await this.envs(
'',
{ position: -1 },
{ name: { [Op.not]: null } },
);
const groups = _.groupBy(envs, 'name');
const envs = await this.envs('', {
name: { [Op.not]: null },
status: EnvStatus.normal,
});
const groups = groupBy(envs, 'name');
let env_string = '';
for (const key in groups) {
if (Object.prototype.hasOwnProperty.call(groups, key)) {
const group = groups[key];
// 忽略不符合bash要求的环境变量名称
if (/^[a-zA-Z_][0-9a-zA-Z_]+$/.test(key)) {
let value = _(group)
.filter((x) => x.status !== EnvStatus.disabled)
.map('value')
if (/^[a-zA-Z_][0-9a-zA-Z_]*$/.test(key)) {
let value = group
.map((x) => x.value)
.join('&')
.replace(/(\\)[^n]/g, '\\\\')
.replace(/(\\$)/, '\\\\')
@@ -6,6 +6,7 @@ import got from 'got';
import nodemailer from 'nodemailer';
import crypto from 'crypto';
import { HttpProxyAgent, HttpsProxyAgent } from 'hpagent';
import { parseBody, parseHeaders } from '../config/util';
@Service()
export default class NotificationService {
@@ -23,15 +24,21 @@ export default class NotificationService {
['dingtalkBot', this.dingtalkBot],
['weWorkBot', this.weWorkBot],
['weWorkApp', this.weWorkApp],
['aibotk', this.aibotk],
['iGot', this.iGot],
['pushPlus', this.pushPlus],
['email', this.email],
['webhook', this.webhook],
['lark', this.lark],
]);
private timeout = 10000;
private title = '';
private content = '';
private params!: Omit<NotificationInfo, 'type'>;
private gotOption = {
timeout: 30000,
retry: 1,
};
constructor(@Inject('logger') private logger: winston.Logger) {}
@@ -74,8 +81,7 @@ export default class NotificationService {
const { gotifyUrl, gotifyToken, gotifyPriority } = this.params;
const res: any = await got
.post(`${gotifyUrl}/message?token=${gotifyToken}`, {
timeout: this.timeout,
retry: 0,
...this.gotOption,
body: `title=${encodeURIComponent(
this.title,
)}&message=${encodeURIComponent(
@@ -93,8 +99,7 @@ export default class NotificationService {
const { goCqHttpBotQq, goCqHttpBotToken, goCqHttpBotUrl } = this.params;
const res: any = await got
.post(`${goCqHttpBotUrl}?${goCqHttpBotQq}`, {
timeout: this.timeout,
retry: 0,
...this.gotOption,
json: { message: `${this.title}\n${this.content}` },
headers: { Authorization: 'Bearer ' + goCqHttpBotToken },
})
@@ -109,8 +114,7 @@ export default class NotificationService {
: `https://sc.ftqq.com/${serverChanKey}.send`;
const res: any = await got
.post(url, {
timeout: this.timeout,
retry: 0,
...this.gotOption,
body: `title=${this.title}&desp=${this.content}`,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
})
@@ -119,12 +123,11 @@ export default class NotificationService {
}
private async pushDeer() {
const { pushDeerKey } = this.params;
const url = `https://api2.pushdeer.com/message/push`;
const { pushDeerKey, pushDeerUrl } = this.params;
const url = pushDeerUrl || `https://api2.pushdeer.com/message/push`;
const res: any = await got
.post(url, {
timeout: this.timeout,
retry: 0,
...this.gotOption,
body: `pushkey=${pushDeerKey}&text=${encodeURIComponent(
this.title,
)}&desp=${encodeURIComponent(this.content)}&type=markdown`,
@@ -141,8 +144,7 @@ export default class NotificationService {
const url = `${chatUrl}${chatToken}`;
const res: any = await got
.post(url, {
timeout: this.timeout,
retry: 0,
...this.gotOption,
body: `payload={"text":"${this.title}\n${this.content}"}`,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
})
@@ -162,8 +164,7 @@ export default class NotificationService {
)}?icon=${barkIcon}?sound=${barkSound}&group=${barkGroup}`;
const res: any = await got
.get(url, {
timeout: this.timeout,
retry: 0,
...this.gotOption,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
})
.json();
@@ -201,8 +202,7 @@ export default class NotificationService {
}
const res: any = await got
.post(url, {
timeout: this.timeout,
retry: 0,
...this.gotOption,
body: `chat_id=${telegramBotUserId}&text=${this.title}\n\n${this.content}&disable_web_page_preview=true`,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
agent,
@@ -224,8 +224,7 @@ export default class NotificationService {
const url = `https://oapi.dingtalk.com/robot/send?access_token=${dingtalkBotToken}${secretParam}`;
const res: any = await got
.post(url, {
timeout: this.timeout,
retry: 0,
...this.gotOption,
json: {
msgtype: 'text',
text: {
@@ -242,8 +241,7 @@ export default class NotificationService {
const url = `https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${weWorkBotKey}`;
const res: any = await got
.post(url, {
timeout: this.timeout,
retry: 0,
...this.gotOption,
json: {
msgtype: 'text',
text: {
@@ -262,8 +260,7 @@ export default class NotificationService {
const url = `https://qyapi.weixin.qq.com/cgi-bin/gettoken`;
const tokenRes: any = await got
.post(url, {
timeout: this.timeout,
retry: 0,
...this.gotOption,
json: {
corpid,
corpsecret,
@@ -313,8 +310,7 @@ export default class NotificationService {
.post(
`https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=${tokenRes.access_token}`,
{
timeout: this.timeout,
retry: 0,
...this.gotOption,
json: {
touser,
agentid,
@@ -328,13 +324,53 @@ export default class NotificationService {
return res.errcode === 0;
}
private async aibotk() {
const { aibotkKey, aibotkType, aibotkName } = this.params;
let url = '';
let json = {};
switch (aibotkType) {
case 'room':
url = 'https://api-bot.aibotk.com/openapi/v1/chat/room';
json = {
apiKey: `${aibotkKey}`,
roomName: `${aibotkName}`,
message: {
type: 1,
content: `【青龙快讯】\n\n${this.title}\n${this.content}`,
},
};
break;
case 'contact':
url = 'https://api-bot.aibotk.com/openapi/v1/chat/contact';
json = {
apiKey: `${aibotkKey}`,
name: `${aibotkName}`,
message: {
type: 1,
content: `【青龙快讯】\n\n${this.title}\n${this.content}`,
},
};
break;
}
const res: any = await got
.post(url, {
...this.gotOption,
json: {
...json,
},
})
.json();
return res.code === 0;
}
private async iGot() {
const { iGotPushKey } = this.params;
const url = `https://push.hellyw.com/${iGotPushKey.toLowerCase()}`;
const res: any = await got
.post(url, {
timeout: this.timeout,
retry: 0,
...this.gotOption,
body: `title=${this.title}&content=${this.content}`,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
})
@@ -348,8 +384,7 @@ export default class NotificationService {
const url = `https://www.pushplus.plus/send`;
const res: any = await got
.post(url, {
timeout: this.timeout,
retry: 0,
...this.gotOption,
json: {
token: `${pushPlusToken}`,
title: `${this.title}`,
@@ -362,6 +397,21 @@ export default class NotificationService {
return res.code === 200;
}
private async lark() {
const { larkKey } = this.params;
const res: any = await got
.post(`https://open.feishu.cn/open-apis/bot/v2/hook/${larkKey}`, {
...this.gotOption,
json: {
msg_type: 'text',
content: { text: `${this.title}\n\n${this.content}` },
},
headers: { 'Content-Type': 'application/json' },
})
.json();
return res.StatusCode === 0;
}
private async email() {
const { emailPass, emailService, emailUser } = this.params;
const transporter = nodemailer.createTransport({
@@ -383,4 +433,62 @@ export default class NotificationService {
return !!info.messageId;
}
private async webhook() {
const {
webhookUrl,
webhookBody,
webhookHeaders,
webhookMethod,
webhookContentType,
} = this.params;
const { formatBody, formatUrl } = this.formatNotifyContent(
webhookUrl,
webhookBody,
);
if (!formatUrl && !formatBody) {
return false;
}
const headers = parseHeaders(webhookHeaders);
const body = parseBody(formatBody, webhookContentType);
const bodyParam = this.formatBody(webhookContentType, body);
const options = {
method: webhookMethod,
headers,
...this.gotOption,
allowGetBody: true,
...bodyParam,
};
const res = await got(formatUrl, options);
return String(res.statusCode).startsWith('20');
}
private formatBody(contentType: string, body: any): object {
if (!body) return {};
switch (contentType) {
case 'application/json':
return { json: body };
case 'multipart/form-data':
return { form: body };
case 'application/x-www-form-urlencoded':
return { body };
}
return {};
}
private formatNotifyContent(url: string, body: string) {
if (!url.includes('$title') && !body.includes('$title')) {
return {};
}
return {
formatUrl: url
.replaceAll('$title', encodeURIComponent(this.title))
.replaceAll('$content', encodeURIComponent(this.content)),
formatBody: body
.replaceAll('$title', this.title)
.replaceAll('$content', this.content),
};
}
}
@@ -119,7 +119,7 @@ export default class OpenService {
(x) => x.expiration >= timestamp,
);
let tokens = invalidTokens;
if (invalidTokens.length > 5) {
if (invalidTokens.length >= 5) {
tokens = [
...invalidTokens.slice(0, 4),
{ ...invalidTokens[4], expiration },
@@ -42,7 +42,11 @@ export default class ScheduleService {
constructor(@Inject('logger') private logger: winston.Logger) {}
async runTask(command: string, callbacks: TaskCallbacks = {}) {
async runTask(
command: string,
callbacks: TaskCallbacks = {},
completionTime: 'start' | 'end' = 'end',
) {
return new Promise(async (resolve, reject) => {
try {
const startTime = dayjs();
@@ -52,6 +56,7 @@ export default class ScheduleService {
// TODO:
callbacks.onStart?.(cp, startTime);
completionTime === 'start' && resolve(cp.pid);
cp.stdout.on('data', async (data) => {
await callbacks.onLog?.(data.toString());
@@ -100,7 +105,6 @@ export default class ScheduleService {
error,
);
await callbacks.onError?.(JSON.stringify(error));
resolve(null);
}
});
}
@@ -6,6 +6,8 @@ import SockService from './sock';
import CronService from './cron';
import ScheduleService, { TaskCallbacks } from './schedule';
import config from '../config';
import { LOG_END_SYMBOL } from '../config/const';
import { getPid, killTask } from '../config/util';
@Service()
export default class ScriptService {
@@ -41,22 +43,24 @@ export default class ScriptService {
public async runScript(filePath: string) {
const relativePath = path.relative(config.scriptPath, filePath);
const command = `task -l ${relativePath} now`;
this.scheduleService.runTask(command, this.taskCallbacks(filePath));
const pid = await this.scheduleService.runTask(
command,
this.taskCallbacks(filePath),
'start',
);
return { code: 200 };
return { code: 200, data: pid };
}
public async stopScript(filePath: string) {
const relativePath = path.relative(config.scriptPath, filePath);
const err = await this.cronService.killTask(`task -l ${relativePath} now`);
const str = err ? `\n${err}` : '';
this.sockService.sendMessage({
type: 'manuallyRunScript',
message: `${str}\n## 执行结束... ${new Date()
.toLocaleString('zh', { hour12: false })
.replace(' 24:', ' 00:')} `,
});
public async stopScript(filePath: string, pid: number) {
let str = '';
if (!pid) {
const relativePath = path.relative(config.scriptPath, filePath);
pid = await getPid(`task -l ${relativePath} now`);
}
try {
await killTask(pid);
} catch (error) {}
return { code: 200 };
}
@@ -14,7 +14,7 @@ export default class SshKeyService {
private generatePrivateKeyFile(alias: string, key: string): void {
try {
fs.writeFileSync(`${this.sshPath}/${alias}`, key, {
fs.writeFileSync(`${this.sshPath}/${alias}`, `${key}${os.EOL}`, {
encoding: 'utf8',
mode: '400',
});
@@ -38,8 +38,16 @@ export default class SshKeyService {
}
}
private generateSingleSshConfig(alias: string, host: string): string {
return `\nHost ${alias}\n Hostname ${host}\n IdentityFile ${this.sshPath}/${alias}\n StrictHostKeyChecking no`;
private generateSingleSshConfig(
alias: string,
host: string,
proxy?: string,
): string {
if (host === 'github.com') {
host = `ssh.github.com\n Port 443\n HostkeyAlgorithms +ssh-rsa\n PubkeyAcceptedAlgorithms +ssh-rsa`;
}
const proxyStr = proxy ? ` ProxyCommand nc -v -x ${proxy} %h %p\n` : '';
return `\nHost ${alias}\n Hostname ${host}\n IdentityFile ${this.sshPath}/${alias}\n StrictHostKeyChecking no\n${proxyStr}`;
}
private generateSshConfig(configs: string[]) {
@@ -69,16 +77,21 @@ export default class SshKeyService {
}
}
public addSSHKey(key: string, alias: string, host: string): void {
public addSSHKey(
key: string,
alias: string,
host: string,
proxy?: string,
): void {
this.generatePrivateKeyFile(alias, key);
const config = this.generateSingleSshConfig(alias, host);
const config = this.generateSingleSshConfig(alias, host, proxy);
this.removeSshConfig(alias);
this.generateSshConfig([config]);
}
public removeSSHKey(alias: string, host: string): void {
public removeSSHKey(alias: string, host: string, proxy?: string): void {
this.removePrivateKeyFile(alias);
const config = this.generateSingleSshConfig(alias, host);
const config = this.generateSingleSshConfig(alias, host, proxy);
this.removeSshConfig(config);
}
}
@@ -19,9 +19,9 @@ import {
concurrentRun,
fileExist,
createFile,
killTask,
} from '../config/util';
import { promises, existsSync } from 'fs';
import { promisify } from 'util';
import { Op } from 'sequelize';
import path from 'path';
import ScheduleService, { TaskCallbacks } from './schedule';
@@ -29,6 +29,7 @@ import { SimpleIntervalSchedule } from 'toad-scheduler';
import SockService from './sock';
import SshKeyService from './sshKey';
import dayjs from 'dayjs';
import { LOG_END_SYMBOL } from '../config/const';
@Service()
export default class SubscriptionService {
@@ -62,7 +63,10 @@ export default class SubscriptionService {
try {
const result = await SubscriptionModel.findAll({
where: query,
order: [['createdAt', 'DESC']],
order: [
['is_disabled', 'ASC'],
['createdAt', 'DESC'],
],
});
return result as any;
} catch (error) {
@@ -73,13 +77,21 @@ export default class SubscriptionService {
private formatCommand(doc: Subscription, url?: string) {
let command = 'ql ';
let _url = url || this.formatUrl(doc).url;
const { type, whitelist, blacklist, dependences, branch, extensions } = doc;
const {
type,
whitelist,
blacklist,
dependences,
branch,
extensions,
proxy,
} = doc;
if (type === 'file') {
command += `raw "${_url}"`;
} else {
command += `repo "${_url}" "${whitelist || ''}" "${blacklist || ''}" "${
dependences || ''
}" "${branch || ''}" "${extensions || ''}"`;
}" "${branch || ''}" "${extensions || ''}" "${proxy || ''}"`;
}
return command;
}
@@ -113,9 +125,10 @@ export default class SubscriptionService {
(doc.pull_option as any).private_key,
doc.alias,
host,
doc.proxy,
);
} else {
this.sshKeyService.removeSSHKey(doc.alias, host);
this.sshKeyService.removeSSHKey(doc.alias, host, doc.proxy);
}
}
@@ -229,7 +242,7 @@ export default class SubscriptionService {
absolutePath,
`\n## 执行结束... ${endTime.format(
'YYYY-MM-DD HH:mm:ss',
)} ${diff} `,
)} ${diff} ${LOG_END_SYMBOL}`,
);
await SubscriptionModel.update(
@@ -338,19 +351,18 @@ export default class SubscriptionService {
for (const doc of docs) {
if (doc.pid) {
try {
process.kill(-doc.pid);
await killTask(doc.pid);
} catch (error) {
this.logger.silly(error);
}
}
const command = this.formatCommand(doc);
const err = await this.killTask(command);
const absolutePath = await this.handleLogPath(doc.log_path as string);
const str = err ? `\n${err}` : '';
fs.appendFileSync(
`${absolutePath}`,
`${str}\n## 执行结束... ${dayjs().format('YYYY-MM-DD HH:mm:ss')} `,
`\n## 执行结束... ${dayjs().format(
'YYYY-MM-DD HH:mm:ss',
)}${LOG_END_SYMBOL}`,
);
}
@@ -360,41 +372,6 @@ export default class SubscriptionService {
);
}
public async killTask(name: string) {
let taskCommand = `ps -ef | grep "${name}" | grep -v grep | awk '{print $1}'`;
const execAsync = promisify(exec);
try {
let pid = (await execAsync(taskCommand)).stdout;
if (pid) {
pid = (await execAsync(`pstree -p ${pid}`)).stdout;
} else {
return;
}
let pids = pid.match(/\(\d+/g);
const killLogs = [];
if (pids && pids.length > 0) {
// node 执行脚本时还会有10个子进程,但是ps -ef中不存在,所以截取前三个
for (const id of pids) {
const c = `kill -9 ${id.slice(1)}`;
try {
const { stdout, stderr } = await execAsync(c);
if (stderr) {
killLogs.push(stderr);
}
if (stdout) {
killLogs.push(stdout);
}
} catch (error: any) {
killLogs.push(error.message);
}
}
}
return killLogs.length > 0 ? JSON.stringify(killLogs) : '';
} catch (e) {
return JSON.stringify(e);
}
}
private async runSingle(subscriptionId: number) {
const subscription = await this.getDb({ id: subscriptionId });
if (subscription.status !== SubscriptionStatus.queued) {
@@ -2,7 +2,6 @@ import { Service, Inject } from 'typedi';
import winston from 'winston';
import config from '../config';
import * as fs from 'fs';
import _ from 'lodash';
import { AuthDataType, AuthInfo, AuthModel, LoginStatus } from '../data/auth';
import { NotificationInfo } from '../data/notify';
import NotificationService from './notify';
@@ -10,6 +9,7 @@ import ScheduleService from './schedule';
import { spawn } from 'child_process';
import SockService from './sock';
import got from 'got';
import { parseContentVersion, parseVersion } from '../config/util';
@Service()
export default class SystemService {
@@ -70,9 +70,8 @@ export default class SystemService {
};
await this.scheduleService.cancelIntervalTask(cron);
if (frequency > 0) {
await this.scheduleService.createIntervalTask(cron, {
this.scheduleService.createIntervalTask(cron, {
days: frequency,
runImmediately: true,
});
}
return { code: 200, data: { ...cron } };
@@ -80,32 +79,33 @@ export default class SystemService {
public async checkUpdate() {
try {
const versionRegx = /.*export const version = \'(.*)\'\;/;
const logRegx = /.*export const changeLog = \`((.*\n.*)+)\`;/;
const currentVersionContent = await parseVersion(config.versionFile);
const currentVersionFile = fs.readFileSync(config.versionFile, 'utf8');
const currentVersion = currentVersionFile.match(versionRegx)![1];
let lastVersion = '';
let lastLog = '';
let lastVersionContent;
try {
const result = await got.get(config.lastVersionFile, {
timeout: 6000,
retry: 0,
});
const lastVersionFileContent = result.body;
lastVersion = lastVersionFileContent.match(versionRegx)![1];
lastLog = lastVersionFileContent.match(logRegx)
? lastVersionFileContent.match(logRegx)![1]
: '';
const result = await got.get(
`${config.lastVersionFile}?t=${Date.now()}`,
{
timeout: 30000,
},
);
lastVersionContent = await parseContentVersion(result.body);
} catch (error) {}
if (!lastVersionContent) {
lastVersionContent = currentVersionContent;
}
return {
code: 200,
data: {
hasNewVersion: this.checkHasNewVersion(currentVersion, lastVersion),
lastVersion,
lastLog,
hasNewVersion: this.checkHasNewVersion(
currentVersionContent.version,
lastVersionContent.version,
),
lastVersion: lastVersionContent.version,
lastLog: lastVersionContent.changeLog,
lastLogLink: lastVersionContent.changeLogLink,
},
};
} catch (error: any) {
@@ -138,10 +138,6 @@ export default class SystemService {
public async updateSystem() {
const cp = spawn('ql -l update', { shell: '/bin/bash' });
this.sockService.sendMessage({
type: 'updateSystemVersion',
message: `开始更新系统`,
});
cp.stdout.on('data', (data) => {
this.sockService.sendMessage({
type: 'updateSystemVersion',
@@ -3,7 +3,6 @@ import winston from 'winston';
import { createRandomString, getNetIp, getPlatform } from '../config/util';
import config from '../config';
import * as fs from 'fs';
import _ from 'lodash';
import jwt from 'jsonwebtoken';
import { authenticator } from '@otplib/preset-default';
import { AuthDataType, AuthInfo, AuthModel, LoginStatus } from '../data/auth';
@@ -65,32 +64,37 @@ export default class UserService {
return this.initAuthInfo();
}
if (retries > 2 && Date.now() - lastlogon < Math.pow(3, retries) * 1000) {
const retriesTime = Math.pow(3, retries) * 1000;
if (retries > 2 && timestamp - lastlogon < retriesTime) {
const waitTime = Math.ceil(
(retriesTime - (timestamp - lastlogon)) / 1000,
);
return {
code: 410,
message: `失败次数过多,请${Math.round(
(Math.pow(3, retries) * 1000 - Date.now() + lastlogon) / 1000,
)}`,
data: Math.round(
(Math.pow(3, retries) * 1000 - Date.now() + lastlogon) / 1000,
),
message: `失败次数过多,请${waitTime}秒后重试`,
data: waitTime,
};
}
if (
username === cUsername &&
password === cPassword &&
twoFactorActivated &&
needTwoFactor
) {
this.updateAuthInfo(content, {
isTwoFactorChecking: true,
});
return {
code: 420,
message: '',
};
}
const { ip, address } = await getNetIp(req);
if (username === cUsername && password === cPassword) {
if (twoFactorActivated && needTwoFactor) {
this.updateAuthInfo(content, {
isTwoFactorChecking: true,
});
return {
code: 420,
message: '请输入两步验证token',
};
}
const data = createRandomString(50, 100);
const expiration = twoFactorActivated ? 30 : 3;
const expiration = twoFactorActivated ? 60 : 20;
let token = jwt.sign({ data }, config.secret as any, {
expiresIn: 60 * 60 * 24 * expiration,
algorithm: 'HS384',
@@ -155,7 +159,16 @@ export default class UserService {
status: LoginStatus.fail,
},
});
return { code: 400, message: config.authError };
if (retries > 2) {
const waitTime = Math.round(Math.pow(3, retries + 1));
return {
code: 410,
message: `失败次数过多,请${waitTime}秒后重试`,
data: waitTime,
};
} else {
return { code: 400, message: config.authError };
}
}
} else {
return this.initAuthInfo();
+9 -3
View File
@@ -5,6 +5,7 @@ import LoggerInstance from './loaders/logger';
import fs from 'fs';
import config from './config';
import path from 'path';
import os from 'os';
const tokenFile = path.join(config.configPath, 'token.json');
@@ -25,9 +26,14 @@ async function getToken() {
async function writeFile(data: any) {
return new Promise<void>((resolve, reject) => {
fs.writeFile(tokenFile, JSON.stringify(data), { encoding: 'utf8' }, () => {
resolve();
});
fs.writeFile(
tokenFile,
`${JSON.stringify(data)}${os.EOL}`,
{ encoding: 'utf8' },
() => {
resolve();
},
);
});
}
@@ -1,12 +1,15 @@
{
"compilerOptions": {
"target": "es2017",
"lib": ["es2017", "esnext.asynciterable", "DOM"],
"lib": ["es2021", "esnext.asynciterable", "DOM"],
"typeRoots": [
"./node_modules/@types",
"./src/types",
"./node_modules/celebrate/lib/index.d.ts"
],
"paths": {
"@/*": ["./back/*"]
},
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
+12
View File
@@ -0,0 +1,12 @@
declare module '*.css';
declare module '*.less';
declare module '*.png';
declare module '*.svg' {
export function ReactComponent(
props: React.SVGProps<SVGSVGElement>,
): React.ReactElement;
const url: string;
export default url;
}
declare module 'pstree.remy';
+6
View File
@@ -0,0 +1,6 @@
{
"watch": ["src"],
"ext": "js,ts,json",
"ignore": ["src/**/*.spec.ts"],
"exec": "ts-node --transpile-only ./src/env.ts"
}
+16
View File
@@ -0,0 +1,16 @@
{
"name": "@qinglong/env",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "nodemon",
"build": "tsc"
},
"dependencies": {
"dotenv": "^16.0.0"
},
"keywords": [],
"author": "",
"license": "ISC"
}
+22
View File
@@ -0,0 +1,22 @@
import dotenv from 'dotenv';
import path from 'path';
if (!process.env.QL_DIR) {
// 声明QL_DIR环境变量
let qlHomePath = path.join(__dirname, '../../../');
// 生产环境
if (qlHomePath.endsWith('/static/')) {
qlHomePath = path.join(qlHomePath, '../');
}
process.env.QL_DIR = qlHomePath.replace(/\/$/g, '');
}
const rootPath = process.env.QL_DIR as string;
const envFound = dotenv.config({ path: path.join(rootPath, '.env') });
if (envFound.error) {
throw new Error("⚠️ Couldn't find .env file ⚠️");
}
const envs = process.env;
console.log(envs);
export default { ...envs };
+28
View File
@@ -0,0 +1,28 @@
{
"compilerOptions": {
"target": "es2017",
"lib": ["es2021", "esnext.asynciterable", "DOM"],
"typeRoots": [
"./node_modules/@types",
"./src/types",
"./node_modules/celebrate/lib/index.d.ts"
],
"paths": {
"@/*": ["./src/*"]
},
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"module": "commonjs",
"pretty": true,
"sourceMap": true,
"outDir": "./lib",
"allowJs": true,
"noEmit": false,
"esModuleInterop": true
},
"include": ["./src/**/*"],
"exclude": ["node_modules", "tests"]
}
+6
View File
@@ -0,0 +1,6 @@
{
"watch": ["src"],
"ext": "js,ts,json",
"ignore": ["src/**/*.spec.ts"],
"exec": "ts-node --transpile-only ./src/public.ts"
}
+11
View File
@@ -0,0 +1,11 @@
{
"name": "@qinglong/public",
"private": true,
"scripts": {
"start": "nodemon",
"build": "tsc"
},
"dependencies": {
"@qinglong/env": "workspace:*"
}
}
@@ -1,7 +1,6 @@
import express from 'express';
import { exec } from 'child_process';
import Logger from './loaders/logger';
import config from './config';
import env from '@qinglong/env';
const app = express();
@@ -16,15 +15,11 @@ app.get('/api/public/panel/log', (req, res) => {
},
);
});
console.log(env);
app
.listen(config.publicPort, async () => {
await require('./loaders/sentry').default({ expressApp: app });
await require('./loaders/db').default();
Logger.debug(`✌️ Back server launched on port ${config.publicPort}`);
.listen(env.PUBLIC_PORT, async () => {
console.log('启动成功');
})
.on('error', (err) => {
Logger.error(err);
process.exit(1);
});
+28
View File
@@ -0,0 +1,28 @@
{
"compilerOptions": {
"target": "es2017",
"lib": ["es2021", "esnext.asynciterable", "DOM"],
"typeRoots": [
"./node_modules/@types",
"./src/types",
"./node_modules/celebrate/lib/index.d.ts"
],
"paths": {
"@/*": ["./back/*"]
},
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"module": "commonjs",
"pretty": true,
"sourceMap": true,
"outDir": "./static/build",
"allowJs": true,
"noEmit": false,
"esModuleInterop": true
},
"include": ["./back/**/*"],
"exclude": ["node_modules", "tests"]
}
+6
View File
@@ -0,0 +1,6 @@
{
"watch": ["src"],
"ext": "js,ts,json",
"ignore": ["src/**/*.spec.ts"],
"exec": "ts-node --transpile-only ./src/public.ts"
}
+138
View File
@@ -0,0 +1,138 @@
{
"name": "@qinglong/schedule",
"private": true,
"scripts": {
"start": "nodemon",
"build": "tsc"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,less,md,json}": [
"prettier --write"
],
"*.ts?(x)": [
"prettier --parser=typescript --write"
]
},
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"react",
"react-dom",
"antd",
"dva",
"postcss",
"webpack",
"eslint",
"stylelint",
"redux",
"@babel/core",
"monaco-editor",
"rc-field-form",
"@types/lodash.merge",
"rollup"
],
"allowedVersions": {
"react": "18",
"react-dom": "18",
"dva-core": "2"
}
}
},
"dependencies": {
"@otplib/preset-default": "^12.0.1",
"@sentry/node": "^7.12.1",
"@sentry/tracing": "^7.12.1",
"body-parser": "^1.19.2",
"celebrate": "^15.0.1",
"chokidar": "^3.5.3",
"cors": "^2.8.5",
"cron-parser": "^4.2.1",
"dayjs": "^1.11.2",
"dotenv": "^16.0.0",
"express": "^4.17.3",
"express-jwt": "^6.1.1",
"express-urlrewrite": "^1.4.0",
"form-data": "^4.0.0",
"got": "^11.8.2",
"hpagent": "^0.1.2",
"iconv-lite": "^0.6.3",
"js-yaml": "^4.1.0",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.21",
"multer": "^1.4.4",
"nedb": "^1.8.0",
"node-schedule": "^2.1.0",
"nodemailer": "^6.7.2",
"pstree.remy": "^1.1.8",
"reflect-metadata": "^0.1.13",
"sequelize": "^6.25.5",
"serve-handler": "^6.1.3",
"sockjs": "^0.3.24",
"sqlite3": "npm:@louislam/sqlite3@^15.0.6",
"toad-scheduler": "^1.6.0",
"typedi": "^0.10.0",
"uuid": "^8.3.2",
"winston": "^3.6.0",
"yargs": "^17.3.1"
},
"devDependencies": {
"@ant-design/icons": "^4.7.0",
"@ant-design/pro-layout": "^6.33.1",
"@monaco-editor/react": "4.4.6",
"@react-hook/resize-observer": "^1.2.6",
"@sentry/react": "^7.12.1",
"@types/body-parser": "^1.19.2",
"@types/cors": "^2.8.12",
"@types/express": "^4.17.13",
"@types/express-jwt": "^6.0.4",
"@types/js-yaml": "^4.0.5",
"@types/jsonwebtoken": "^8.5.8",
"@types/lodash": "^4.14.185",
"@types/multer": "^1.4.7",
"@types/nedb": "^1.8.12",
"@types/node": "^17.0.21",
"@types/node-schedule": "^1.3.2",
"@types/nodemailer": "^6.4.4",
"@types/qrcode.react": "^1.0.2",
"@types/react": "^18.0.20",
"@types/react-dom": "^18.0.6",
"@types/serve-handler": "^6.1.1",
"@types/sockjs": "^0.3.33",
"@types/sockjs-client": "^1.5.1",
"@types/uuid": "^8.3.4",
"@umijs/max": "^4.0.21",
"@umijs/ssr-darkreader": "^4.9.45",
"ansi-to-react": "^6.1.6",
"antd": "^4.23.0",
"antd-img-crop": "^4.2.3",
"codemirror": "^5.65.2",
"compression-webpack-plugin": "9.2.0",
"concurrently": "^7.0.0",
"lint-staged": "^13.0.3",
"monaco-editor": "^0.34.1",
"nodemon": "^2.0.15",
"prettier": "^2.5.1",
"qiniu": "^7.4.0",
"qrcode.react": "^1.0.1",
"query-string": "^7.1.1",
"rc-tween-one": "^3.0.6",
"react": "18.2.0",
"react-codemirror2": "^7.2.1",
"react-diff-viewer": "^3.1.1",
"react-dnd": "^14.0.2",
"react-dnd-html5-backend": "^14.0.0",
"react-dom": "18.2.0",
"react-split-pane": "^0.1.92",
"sockjs-client": "^1.6.0",
"ts-node": "^10.6.0",
"tslib": "^2.4.0",
"typescript": "4.8.4",
"umi-request": "^1.4.0",
"vh-check": "^2.0.5",
"webpack": "^5.70.0",
"yorkie": "^2.0.0"
}
}
@@ -18,14 +18,15 @@ const run = async () => {
_schedule &&
_schedule.length > 5 &&
task.status !== CrontabStatus.disabled &&
!task.isDisabled
!task.isDisabled &&
task.schedule
) {
schedule.scheduleJob(task.schedule, function () {
let command = task.command as string;
if (!command.includes('task ') && !command.includes('ql ')) {
command = `task ${command}`;
}
exec(command);
exec(`ID=${task.id} ${command}`);
});
}
}
@@ -43,11 +44,7 @@ app
await require('./loaders/db').default();
await run();
Logger.info(`
################################################
🛡 Schedule listening on port: ${config.cronPort} 🛡
################################################
`);
Logger.debug('定时任务服务启动成功!');
})
.on('error', (err) => {
Logger.error(err);
+28
View File
@@ -0,0 +1,28 @@
{
"compilerOptions": {
"target": "es2017",
"lib": ["es2021", "esnext.asynciterable", "DOM"],
"typeRoots": [
"./node_modules/@types",
"./src/types",
"./node_modules/celebrate/lib/index.d.ts"
],
"paths": {
"@/*": ["./back/*"]
},
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"module": "commonjs",
"pretty": true,
"sourceMap": true,
"outDir": "./static/build",
"allowJs": true,
"noEmit": false,
"esModuleInterop": true
},
"include": ["./back/**/*"],
"exclude": ["node_modules", "tests"]
}
+11 -16
View File
@@ -1,20 +1,15 @@
import { defineConfig } from 'umi';
import { defineConfig } from '@umijs/max';
const CompressionPlugin = require('compression-webpack-plugin');
export default defineConfig({
hash: true,
layout: false,
antd: {},
outputPath: 'static/dist',
nodeModulesTransform: {
type: 'none',
fastRefresh: true,
favicons: ['/images/favicon.svg'],
mfsu: {
strategy: 'eager',
},
fastRefresh: {},
esbuild: {},
webpack5: {},
dynamicImport: {
loading: '@/components/pageLoading',
},
favicon: '/images/favicon.svg',
proxy: {
'/api/public': {
target: 'http://127.0.0.1:5400/',
@@ -26,7 +21,7 @@ export default defineConfig({
ws: true,
},
},
chainWebpack: (config) => {
chainWebpack: ((config: any) => {
config.plugin('compression-webpack-plugin').use(
new CompressionPlugin({
algorithm: 'gzip',
@@ -35,13 +30,13 @@ export default defineConfig({
minRatio: 0.6,
}),
);
},
}) as any,
externals: {
react: 'window.React',
'react-dom': 'window.ReactDOM',
},
scripts: [
'https://gw.alipayobjects.com/os/lib/react/16.13.1/umd/react.production.min.js',
'https://gw.alipayobjects.com/os/lib/react-dom/16.13.1/umd/react-dom.production.min.js',
headScripts: [
'https://gw.alipayobjects.com/os/lib/react/18.2.0/umd/react.production.min.js',
'https://gw.alipayobjects.com/os/lib/react-dom/18.2.0/umd/react-dom.production.min.js',
],
});
+138
View File
@@ -0,0 +1,138 @@
{
"name": "@qinglong/web",
"private": true,
"scripts": {
"start": "max dev",
"build": "max build"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.{js,jsx,less,md,json}": [
"prettier --write"
],
"*.ts?(x)": [
"prettier --parser=typescript --write"
]
},
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"react",
"react-dom",
"antd",
"dva",
"postcss",
"webpack",
"eslint",
"stylelint",
"redux",
"@babel/core",
"monaco-editor",
"rc-field-form",
"@types/lodash.merge",
"rollup"
],
"allowedVersions": {
"react": "18",
"react-dom": "18",
"dva-core": "2"
}
}
},
"dependencies": {
"@otplib/preset-default": "^12.0.1",
"@sentry/node": "^7.12.1",
"@sentry/tracing": "^7.12.1",
"body-parser": "^1.19.2",
"celebrate": "^15.0.1",
"chokidar": "^3.5.3",
"cors": "^2.8.5",
"cron-parser": "^4.2.1",
"dayjs": "^1.11.2",
"dotenv": "^16.0.0",
"express": "^4.17.3",
"express-jwt": "^6.1.1",
"express-urlrewrite": "^1.4.0",
"form-data": "^4.0.0",
"got": "^11.8.2",
"hpagent": "^0.1.2",
"iconv-lite": "^0.6.3",
"js-yaml": "^4.1.0",
"jsonwebtoken": "^8.5.1",
"lodash": "^4.17.21",
"multer": "^1.4.4",
"nedb": "^1.8.0",
"node-schedule": "^2.1.0",
"nodemailer": "^6.7.2",
"pstree.remy": "^1.1.8",
"reflect-metadata": "^0.1.13",
"sequelize": "^6.25.5",
"serve-handler": "^6.1.3",
"sockjs": "^0.3.24",
"sqlite3": "npm:@louislam/sqlite3@^15.0.6",
"toad-scheduler": "^1.6.0",
"typedi": "^0.10.0",
"uuid": "^8.3.2",
"winston": "^3.6.0",
"yargs": "^17.3.1"
},
"devDependencies": {
"@ant-design/icons": "^4.7.0",
"@ant-design/pro-layout": "^6.33.1",
"@monaco-editor/react": "4.4.6",
"@react-hook/resize-observer": "^1.2.6",
"@sentry/react": "^7.12.1",
"@types/body-parser": "^1.19.2",
"@types/cors": "^2.8.12",
"@types/express": "^4.17.13",
"@types/express-jwt": "^6.0.4",
"@types/js-yaml": "^4.0.5",
"@types/jsonwebtoken": "^8.5.8",
"@types/lodash": "^4.14.185",
"@types/multer": "^1.4.7",
"@types/nedb": "^1.8.12",
"@types/node": "^17.0.21",
"@types/node-schedule": "^1.3.2",
"@types/nodemailer": "^6.4.4",
"@types/qrcode.react": "^1.0.2",
"@types/react": "^18.0.20",
"@types/react-dom": "^18.0.6",
"@types/serve-handler": "^6.1.1",
"@types/sockjs": "^0.3.33",
"@types/sockjs-client": "^1.5.1",
"@types/uuid": "^8.3.4",
"@umijs/max": "^4.0.21",
"@umijs/ssr-darkreader": "^4.9.45",
"ansi-to-react": "^6.1.6",
"antd": "^4.23.0",
"antd-img-crop": "^4.2.3",
"codemirror": "^5.65.2",
"compression-webpack-plugin": "9.2.0",
"concurrently": "^7.0.0",
"lint-staged": "^13.0.3",
"monaco-editor": "^0.34.1",
"nodemon": "^2.0.15",
"prettier": "^2.5.1",
"qiniu": "^7.4.0",
"qrcode.react": "^1.0.1",
"query-string": "^7.1.1",
"rc-tween-one": "^3.0.6",
"react": "18.2.0",
"react-codemirror2": "^7.2.1",
"react-diff-viewer": "^3.1.1",
"react-dnd": "^14.0.2",
"react-dnd-html5-backend": "^14.0.0",
"react-dom": "18.2.0",
"react-split-pane": "^0.1.92",
"sockjs-client": "^1.6.0",
"ts-node": "^10.6.0",
"tslib": "^2.4.0",
"typescript": "4.8.4",
"umi-request": "^1.4.0",
"vh-check": "^2.0.5",
"webpack": "^5.70.0",
"yorkie": "^2.0.0"
}
}

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

@@ -0,0 +1,9 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { Outlet, useOutletContext } from 'umi';
export default function EmptyRoute() {
const context = useOutletContext();
return <Outlet context={context} />;
}
@@ -0,0 +1,21 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
interface IDefaultRuntimeConfig {
onRouteChange?: (props: {
routes: any;
clientRoutes: any;
location: any;
action: any;
}) => void;
patchRoutes?: (props: { routes: any }) => void;
patchClientRoutes?: (props: { routes: any }) => void;
render?: (oldRender: () => void) => void;
rootContainer?: (lastRootContainer: JSX.Element, args?: any) => void;
[key: string]: any;
}
export type RuntimeConfig = IDefaultRuntimeConfig;
export function defineApp(config: RuntimeConfig): RuntimeConfig {
return config;
}
@@ -0,0 +1,66 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import {
createHashHistory,
createMemoryHistory,
createBrowserHistory,
History,
} from '/Users/whyour/resp/qinglong/node_modules/.pnpm/@umijs+renderer-react@4.0.21_ef5jwxihqo6n7gxfmzogljlgcm/node_modules/@umijs/renderer-react';
let history: History;
let basename: string = '/';
export function createHistory(opts: any) {
let h;
if (opts.type === 'hash') {
h = createHashHistory();
} else if (opts.type === 'memory') {
h = createMemoryHistory(opts);
} else {
h = createBrowserHistory();
}
if (opts.basename) {
basename = opts.basename;
}
history = {
...h,
push(to, state) {
h.push(patchTo(to), state);
},
replace(to, state) {
h.replace(patchTo(to), state);
},
get location() {
return h.location;
},
get action() {
return h.action;
},
};
return h;
}
// Patch `to` to support basename
// Refs:
// https://github.com/remix-run/history/blob/3e9dab4/packages/history/index.ts#L484
// https://github.com/remix-run/history/blob/dev/docs/api-reference.md#to
function patchTo(to: any) {
if (typeof to === 'string') {
return `${stripLastSlash(basename)}${to}`;
} else if (typeof to === 'object' && to.pathname) {
return {
...to,
pathname: `${stripLastSlash(basename)}${to.pathname}`,
};
} else {
throw new Error(`Unexpected to: ${to}`);
}
}
function stripLastSlash(path) {
return path.slice(-1) === '/' ? path.slice(0, -1) : path;
}
export { history };
@@ -0,0 +1,44 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import { PluginManager } from 'umi';
function __defaultExport(obj) {
if (obj.default) {
return typeof obj.default === 'function' ? obj.default() : obj.default;
}
return obj;
}
export function getPlugins() {
return [];
}
export function getValidKeys() {
return [
'patchRoutes',
'patchClientRoutes',
'modifyContextOpts',
'rootContainer',
'innerProvider',
'i18nProvider',
'accessProvider',
'dataflowProvider',
'outerProvider',
'render',
'onRouteChange',
'qiankun',
];
}
let pluginManager = null;
export function createPluginManager() {
pluginManager = PluginManager.create({
plugins: getPlugins(),
validKeys: getValidKeys(),
});
return pluginManager;
}
export function getPluginManager() {
return pluginManager;
}
+217
View File
@@ -0,0 +1,217 @@
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
// Created by Umi Plugin
export interface IConfigFromPlugins {
clientLoader?: {};
title?: string;
styles?: any[];
scripts?: any[];
routes?: {}[];
reactRouter5Compat?: {};
presets?: string[];
plugins?: string[];
npmClient?: 'pnpm' | 'tnpm' | 'cnpm' | 'yarn' | 'npm';
mountElementId?: string;
metas?: any[];
links?: any[];
historyWithQuery?: {};
history?: {
type?: 'browser' | 'hash' | 'memory';
};
headScripts?: any[];
conventionRoutes?: {
base?: string;
exclude?: any[];
};
base?: string;
writeToDisk?: boolean;
theme?: {};
targets?: {};
svgr?: {};
svgo?: {} | boolean;
styleLoader?: {};
srcTranspiler?: 'babel' | 'esbuild' | 'swc' | 'none';
sassLoader?: {};
runtimePublicPath?: {};
purgeCSS?: {};
publicPath?: string;
proxy?: {} | any[];
postcssLoader?: {};
outputPath?: string;
mfsu?:
| {
cacheDirectory?: string;
chainWebpack?: () => any;
esbuild?: boolean;
exclude?: any[];
include?: string[];
mfName?: string;
remoteAliases?: string[];
remoteName?: string;
runtimePublicPath?: boolean;
shared?: {};
strategy?: 'eager' | 'normal';
}
| boolean;
mdx?: {
loader?: string;
loaderOptions?: {};
};
manifest?: {};
lessLoader?: {};
jsMinifierOptions?: {};
jsMinifier?: 'esbuild' | 'swc' | 'terser' | 'uglifyJs' | 'none';
inlineLimit?: number;
ignoreMomentLocale?: boolean;
https?: {};
hash?: boolean;
forkTSChecker?: {};
fastRefresh?: boolean;
extraPostCSSPlugins?: any[];
extraBabelPresets?: any[];
extraBabelPlugins?: any[];
extraBabelIncludes?: any[];
externals?: {} | string | (() => any);
esm?: {};
devtool?: string | boolean;
depTranspiler?: 'babel' | 'esbuild' | 'swc' | 'none';
define?: {};
deadCode?: {};
cssMinifierOptions?: {};
cssMinifier?: 'cssnano' | 'esbuild' | 'parcelCSS' | 'none';
cssLoaderModules?: {};
cssLoader?: {};
copy?: any[];
chainWebpack?: () => any;
cacheDirectoryPath?: string;
babelLoaderCustomize?: string;
autoprefixer?: {};
autoCSSModules?: boolean;
alias?: {};
crossorigin?:
| boolean
| {
include?: {}[];
};
esmi?: {
cdnOrigin?: string;
shimUrl?: string;
};
favicons?: string[];
mock?: {
exclude?: string[];
include?: string[];
};
mpa?: {
template?: string;
getConfigFromEntryFile?: boolean;
};
polyfill?: {
imports?: string[];
};
routePrefetch?: {};
ssr?: {
serverBuildPath?: string;
platform?: string;
};
terminal?: {};
tmpFiles?: boolean;
lowImport?: {
libs?: any[];
css?: string;
};
vite?: {};
apiRoute?: {
platform?: string;
};
monorepoRedirect?:
| boolean
| {
srcDir?: string[];
exclude?: {}[];
};
clickToComponent?: {
editor?: string;
};
legacy?: {
buildOnly?: boolean;
nodeModulesTransform?: boolean;
};
verifyCommit?: {
scope?: string[];
allowEmoji?: boolean;
};
run?: {
globals?: string[];
};
access?: {} | boolean;
analytics?: {} | boolean;
antd?:
| {
configProvider?: {};
dark?: boolean;
compact?: boolean;
import?: boolean;
style?: 'less' | 'css';
}
| boolean;
dva?:
| {
extraModels?: string[];
immer?: {};
}
| boolean;
initialState?:
| {
loading?: string;
}
| boolean;
layout?: {} | boolean;
locale?:
| {
default?: string;
useLocalStorage?: boolean;
baseNavigator?: boolean;
title?: boolean;
antd?: boolean;
baseSeparator?: string;
}
| boolean;
mf?: {
name?: string;
remotes?: {
aliasName?: string;
name?: string;
entry?: string;
entries?: {};
keyResolver?: string;
}[];
shared?: {};
library?: {};
};
model?:
| {
extraModels?: string[];
}
| boolean;
moment2dayjs?:
| {
preset?: string;
plugins?: any[];
}
| boolean;
qiankun?:
| {
slave?: {};
master?: {};
externalQiankun?: boolean;
}
| boolean;
request?:
| {
dataField?: '';
}
| boolean;
tailwindcss?: {} | boolean;
}
@@ -0,0 +1,392 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.description.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.async-iterator.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.has-instance.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.is-concat-spreadable.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.iterator.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.match.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.match-all.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.replace.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.search.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.species.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.split.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.to-primitive.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.to-string-tag.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.symbol.unscopables.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.error.cause.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.error.to-string.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.aggregate-error.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.aggregate-error.cause.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.at.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.concat.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.copy-within.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.every.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.fill.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.filter.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.find.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.find-index.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.flat.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.flat-map.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.for-each.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.from.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.includes.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.index-of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.is-array.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.iterator.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.join.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.last-index-of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.map.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.reduce.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.reduce-right.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.reverse.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.slice.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.some.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.sort.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.species.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.splice.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.unscopables.flat.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array.unscopables.flat-map.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array-buffer.constructor.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array-buffer.is-view.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.array-buffer.slice.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.data-view.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.date.get-year.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.date.now.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.date.set-year.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.date.to-gmt-string.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.date.to-iso-string.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.date.to-json.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.date.to-primitive.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.date.to-string.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.escape.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.function.bind.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.function.has-instance.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.function.name.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.global-this.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.json.stringify.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.json.to-string-tag.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.map.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.acosh.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.asinh.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.atanh.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.cbrt.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.clz32.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.cosh.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.expm1.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.fround.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.hypot.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.imul.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.log10.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.log1p.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.log2.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.sign.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.sinh.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.tanh.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.to-string-tag.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.math.trunc.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.number.constructor.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.number.epsilon.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.number.is-finite.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.number.is-integer.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.number.is-nan.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.number.is-safe-integer.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.number.max-safe-integer.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.number.min-safe-integer.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.number.parse-float.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.number.parse-int.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.number.to-exponential.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.number.to-fixed.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.number.to-precision.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.assign.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.create.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.define-getter.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.define-properties.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.define-property.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.define-setter.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.entries.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.freeze.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.from-entries.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.get-own-property-descriptor.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.get-own-property-descriptors.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.get-own-property-names.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.get-prototype-of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.has-own.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.is.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.is-extensible.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.is-frozen.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.is-sealed.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.keys.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.lookup-getter.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.lookup-setter.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.prevent-extensions.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.seal.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.set-prototype-of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.to-string.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.object.values.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.parse-float.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.parse-int.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.promise.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.promise.all-settled.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.promise.any.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.promise.finally.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.apply.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.construct.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.define-property.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.delete-property.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.get.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.get-own-property-descriptor.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.get-prototype-of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.has.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.is-extensible.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.own-keys.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.prevent-extensions.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.set.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.set-prototype-of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.reflect.to-string-tag.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.regexp.constructor.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.regexp.dot-all.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.regexp.exec.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.regexp.flags.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.regexp.sticky.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.regexp.test.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.regexp.to-string.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.set.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.at-alternative.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.code-point-at.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.ends-with.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.from-code-point.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.includes.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.iterator.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.match.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.match-all.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.pad-end.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.pad-start.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.raw.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.repeat.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.replace.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.replace-all.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.search.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.split.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.starts-with.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.substr.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.trim.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.trim-end.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.trim-start.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.anchor.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.big.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.blink.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.bold.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.fixed.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.fontcolor.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.fontsize.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.italics.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.link.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.small.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.strike.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.sub.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.string.sup.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.float32-array.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.float64-array.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.int8-array.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.int16-array.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.int32-array.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.uint8-array.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.uint8-clamped-array.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.uint16-array.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.uint32-array.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.at.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.copy-within.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.every.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.fill.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.filter.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.find.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.find-index.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.for-each.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.from.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.includes.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.index-of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.iterator.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.join.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.last-index-of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.map.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.reduce.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.reduce-right.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.reverse.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.set.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.slice.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.some.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.sort.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.subarray.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.to-locale-string.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.typed-array.to-string.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.unescape.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.weak-map.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/es.weak-set.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.from-async.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.filter-out.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.filter-reject.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.find-last.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.find-last-index.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.group-by.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.group-by-to-map.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.is-template-object.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.last-index.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.last-item.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.to-reversed.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.to-sorted.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.to-spliced.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.unique-by.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.array.with.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.constructor.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.as-indexed-pairs.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.drop.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.every.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.filter.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.find.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.flat-map.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.for-each.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.from.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.map.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.reduce.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.some.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.take.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.async-iterator.to-array.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.bigint.range.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.composite-key.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.composite-symbol.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.function.is-callable.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.function.is-constructor.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.function.un-this.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.constructor.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.as-indexed-pairs.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.drop.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.every.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.filter.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.find.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.flat-map.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.for-each.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.from.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.map.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.reduce.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.some.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.take.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.to-array.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.iterator.to-async.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.delete-all.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.emplace.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.every.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.filter.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.find.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.find-key.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.from.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.group-by.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.includes.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.key-by.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.key-of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.map-keys.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.map-values.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.merge.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.reduce.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.some.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.update.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.update-or-insert.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.map.upsert.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.math.clamp.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.math.deg-per-rad.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.math.degrees.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.math.fscale.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.math.iaddh.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.math.imulh.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.math.isubh.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.math.rad-per-deg.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.math.radians.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.math.scale.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.math.seeded-prng.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.math.signbit.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.math.umulh.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.number.from-string.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.number.range.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.object.iterate-entries.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.object.iterate-keys.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.object.iterate-values.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.observable.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.promise.try.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.reflect.define-metadata.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.reflect.delete-metadata.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.reflect.get-metadata.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.reflect.get-metadata-keys.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.reflect.get-own-metadata.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.reflect.get-own-metadata-keys.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.reflect.has-metadata.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.reflect.has-own-metadata.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.reflect.metadata.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.add-all.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.delete-all.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.difference.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.every.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.filter.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.find.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.from.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.intersection.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.is-disjoint-from.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.is-subset-of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.is-superset-of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.join.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.map.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.reduce.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.some.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.symmetric-difference.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.set.union.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.string.at.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.string.cooked.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.string.code-points.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.symbol.async-dispose.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.symbol.dispose.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.symbol.matcher.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.symbol.metadata.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.symbol.observable.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.symbol.pattern-match.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.symbol.replace-all.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.typed-array.from-async.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.typed-array.filter-out.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.typed-array.filter-reject.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.typed-array.find-last.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.typed-array.find-last-index.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.typed-array.group-by.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.typed-array.to-reversed.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.typed-array.to-sorted.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.typed-array.to-spliced.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.typed-array.unique-by.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.typed-array.with.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.weak-map.delete-all.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.weak-map.from.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.weak-map.of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.weak-map.emplace.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.weak-map.upsert.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.weak-set.add-all.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.weak-set.delete-all.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.weak-set.from.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/esnext.weak-set.of.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.atob.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.btoa.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.dom-collections.for-each.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.dom-collections.iterator.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.dom-exception.constructor.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.dom-exception.stack.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.dom-exception.to-string-tag.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.immediate.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.queue-microtask.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.structured-clone.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.timers.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.url.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.url.to-json.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/core-js@3.22.4/node_modules/core-js/modules/web.url-search-params.js';
import '/Users/whyour/resp/qinglong/node_modules/.pnpm/regenerator-runtime@0.13.9/node_modules/regenerator-runtime/runtime.js';
export {};
@@ -0,0 +1,421 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
export async function getRoutes() {
return {
routes: {
'crontab/viewCreateModal': {
path: 'crontab/viewCreateModal',
id: 'crontab/viewCreateModal',
parentId: '@@/global-layout',
file: 'crontab/viewCreateModal.tsx',
},
'crontab/viewManageModal': {
path: 'crontab/viewManageModal',
id: 'crontab/viewManageModal',
parentId: '@@/global-layout',
file: 'crontab/viewManageModal.tsx',
},
'subscription/logModal': {
path: 'subscription/logModal',
id: 'subscription/logModal',
parentId: '@@/global-layout',
file: 'subscription/logModal.tsx',
},
'initialization/index': {
path: 'initialization',
id: 'initialization/index',
parentId: '@@/global-layout',
file: 'initialization/index.tsx',
},
'script/editNameModal': {
path: 'script/editNameModal',
id: 'script/editNameModal',
parentId: '@@/global-layout',
file: 'script/editNameModal.tsx',
},
'setting/notification': {
path: 'setting/notification',
id: 'setting/notification',
parentId: '@@/global-layout',
file: 'setting/notification.tsx',
},
'dependence/logModal': {
path: 'dependence/logModal',
id: 'dependence/logModal',
parentId: '@@/global-layout',
file: 'dependence/logModal.tsx',
},
'setting/checkUpdate': {
path: 'setting/checkUpdate',
id: 'setting/checkUpdate',
parentId: '@@/global-layout',
file: 'setting/checkUpdate.tsx',
},
'subscription/index': {
path: 'subscription',
id: 'subscription/index',
parentId: '@@/global-layout',
file: 'subscription/index.tsx',
},
'subscription/modal': {
path: 'subscription/modal',
id: 'subscription/modal',
parentId: '@@/global-layout',
file: 'subscription/modal.tsx',
},
'env/editNameModal': {
path: 'env/editNameModal',
id: 'env/editNameModal',
parentId: '@@/global-layout',
file: 'env/editNameModal.tsx',
},
'crontab/logModal': {
path: 'crontab/logModal',
id: 'crontab/logModal',
parentId: '@@/global-layout',
file: 'crontab/logModal.tsx',
},
'dependence/index': {
path: 'dependence',
id: 'dependence/index',
parentId: '@@/global-layout',
file: 'dependence/index.tsx',
},
'dependence/modal': {
path: 'dependence/modal',
id: 'dependence/modal',
parentId: '@@/global-layout',
file: 'dependence/modal.tsx',
},
'script/editModal': {
path: 'script/editModal',
id: 'script/editModal',
parentId: '@@/global-layout',
file: 'script/editModal.tsx',
},
'script/saveModal': {
path: 'script/saveModal',
id: 'script/saveModal',
parentId: '@@/global-layout',
file: 'script/saveModal.tsx',
},
'setting/appModal': {
path: 'setting/appModal',
id: 'setting/appModal',
parentId: '@@/global-layout',
file: 'setting/appModal.tsx',
},
'setting/loginLog': {
path: 'setting/loginLog',
id: 'setting/loginLog',
parentId: '@@/global-layout',
file: 'setting/loginLog.tsx',
},
'setting/security': {
path: 'setting/security',
id: 'setting/security',
parentId: '@@/global-layout',
file: 'setting/security.tsx',
},
'crontab/detail': {
path: 'crontab/detail',
id: 'crontab/detail',
parentId: '@@/global-layout',
file: 'crontab/detail.tsx',
},
'script/setting': {
path: 'script/setting',
id: 'script/setting',
parentId: '@@/global-layout',
file: 'script/setting.tsx',
},
'crontab/index': {
path: 'crontab',
id: 'crontab/index',
parentId: '@@/global-layout',
file: 'crontab/index.tsx',
},
'crontab/modal': {
path: 'crontab/modal',
id: 'crontab/modal',
parentId: '@@/global-layout',
file: 'crontab/modal.tsx',
},
'setting/about': {
path: 'setting/about',
id: 'setting/about',
parentId: '@@/global-layout',
file: 'setting/about.tsx',
},
'setting/index': {
path: 'setting',
id: 'setting/index',
parentId: '@@/global-layout',
file: 'setting/index.tsx',
},
'config/index': {
path: 'config',
id: 'config/index',
parentId: '@@/global-layout',
file: 'config/index.tsx',
},
'script/index': {
path: 'script',
id: 'script/index',
parentId: '@@/global-layout',
file: 'script/index.tsx',
},
'error/index': {
path: 'error',
id: 'error/index',
parentId: '@@/global-layout',
file: 'error/index.tsx',
},
'login/index': {
path: 'login',
id: 'login/index',
parentId: '@@/global-layout',
file: 'login/index.tsx',
},
'diff/index': {
path: 'diff',
id: 'diff/index',
parentId: '@@/global-layout',
file: 'diff/index.tsx',
},
'env/index': {
path: 'env',
id: 'env/index',
parentId: '@@/global-layout',
file: 'env/index.tsx',
},
'env/modal': {
path: 'env/modal',
id: 'env/modal',
parentId: '@@/global-layout',
file: 'env/modal.tsx',
},
'log/index': {
path: 'log',
id: 'log/index',
parentId: '@@/global-layout',
file: 'log/index.tsx',
},
'@@/global-layout': {
id: '@@/global-layout',
path: '/',
file: '@/layouts/index.tsx',
isLayout: true,
},
},
routeComponents: {
'crontab/viewCreateModal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__crontab__viewCreateModal" */ '../../../src/pages/crontab/viewCreateModal.tsx'
),
),
'crontab/viewManageModal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__crontab__viewManageModal" */ '../../../src/pages/crontab/viewManageModal.tsx'
),
),
'subscription/logModal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__subscription__logModal" */ '../../../src/pages/subscription/logModal.tsx'
),
),
'initialization/index': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__initialization__index" */ '../../../src/pages/initialization/index.tsx'
),
),
'script/editNameModal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__script__editNameModal" */ '../../../src/pages/script/editNameModal.tsx'
),
),
'setting/notification': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__setting__notification" */ '../../../src/pages/setting/notification.tsx'
),
),
'dependence/logModal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__dependence__logModal" */ '../../../src/pages/dependence/logModal.tsx'
),
),
'setting/checkUpdate': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__setting__checkUpdate" */ '../../../src/pages/setting/checkUpdate.tsx'
),
),
'subscription/index': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__subscription__index" */ '../../../src/pages/subscription/index.tsx'
),
),
'subscription/modal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__subscription__modal" */ '../../../src/pages/subscription/modal.tsx'
),
),
'env/editNameModal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__env__editNameModal" */ '../../../src/pages/env/editNameModal.tsx'
),
),
'crontab/logModal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__crontab__logModal" */ '../../../src/pages/crontab/logModal.tsx'
),
),
'dependence/index': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__dependence__index" */ '../../../src/pages/dependence/index.tsx'
),
),
'dependence/modal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__dependence__modal" */ '../../../src/pages/dependence/modal.tsx'
),
),
'script/editModal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__script__editModal" */ '../../../src/pages/script/editModal.tsx'
),
),
'script/saveModal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__script__saveModal" */ '../../../src/pages/script/saveModal.tsx'
),
),
'setting/appModal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__setting__appModal" */ '../../../src/pages/setting/appModal.tsx'
),
),
'setting/loginLog': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__setting__loginLog" */ '../../../src/pages/setting/loginLog.tsx'
),
),
'setting/security': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__setting__security" */ '../../../src/pages/setting/security.tsx'
),
),
'crontab/detail': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__crontab__detail" */ '../../../src/pages/crontab/detail.tsx'
),
),
'script/setting': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__script__setting" */ '../../../src/pages/script/setting.tsx'
),
),
'crontab/index': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__crontab__index" */ '../../../src/pages/crontab/index.tsx'
),
),
'crontab/modal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__crontab__modal" */ '../../../src/pages/crontab/modal.tsx'
),
),
'setting/about': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__setting__about" */ '../../../src/pages/setting/about.tsx'
),
),
'setting/index': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__setting__index" */ '../../../src/pages/setting/index.tsx'
),
),
'config/index': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__config__index" */ '../../../src/pages/config/index.tsx'
),
),
'script/index': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__script__index" */ '../../../src/pages/script/index.tsx'
),
),
'error/index': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__error__index" */ '../../../src/pages/error/index.tsx'
),
),
'login/index': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__login__index" */ '../../../src/pages/login/index.tsx'
),
),
'diff/index': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__diff__index" */ '../../../src/pages/diff/index.tsx'
),
),
'env/index': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__env__index" */ '../../../src/pages/env/index.tsx'
),
),
'env/modal': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__env__modal" */ '../../../src/pages/env/modal.tsx'
),
),
'log/index': React.lazy(
() =>
import(
/* webpackChunkName: "src__pages__log__index" */ '../../../src/pages/log/index.tsx'
),
),
'@@/global-layout': React.lazy(
() =>
import(
/* webpackChunkName: "layouts__index" */ '@/layouts/index.tsx'
),
),
},
};
}
@@ -0,0 +1,63 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
const console = globalThis.console;
let count = 0;
let groupLevel = 0;
function send(type: string, message?: string) {
if (process.env.NODE_ENV === 'production') {
return;
} else {
const encodedMessage = message ? `&m=${encodeURI(message)}` : '';
fetch(
`/__umi/api/terminal?type=${type}&t=${Date.now()}&c=${count++}&g=${groupLevel}${encodedMessage}`,
{ mode: 'no-cors' },
);
}
}
function prettyPrint(obj: any) {
return JSON.stringify(obj, null, 2);
}
function stringifyObjs(objs: any[]) {
const obj = objs.length > 1 ? objs.map(stringify).join(' ') : objs[0];
return typeof obj === 'object' ? `${prettyPrint(obj)}` : obj.toString();
}
function stringify(obj: any) {
return typeof obj === 'object' ? `${JSON.stringify(obj)}` : obj.toString();
}
const terminal = {
log(...objs: any[]) {
send('log', stringifyObjs(objs));
},
info(...objs: any[]) {
send('info', stringifyObjs(objs));
},
warn(...objs: any[]) {
send('warn', stringifyObjs(objs));
},
error(...objs: any[]) {
send('error', stringifyObjs(objs));
},
group() {
groupLevel++;
},
groupCollapsed() {
groupLevel++;
},
groupEnd() {
groupLevel && --groupLevel;
},
clear() {
send('clear');
},
trace(...args: any[]) {
console.trace(...args);
},
profile(...args: any[]) {
console.profile(...args);
},
profileEnd(...args: any[]) {
console.profileEnd(...args);
},
};
export { terminal };
@@ -0,0 +1,46 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
// @umijs/renderer-*
export {
createBrowserHistory,
createHashHistory,
createMemoryHistory,
createSearchParams,
generatePath,
matchPath,
matchRoutes,
Navigate,
NavLink,
Outlet,
resolvePath,
useLocation,
useMatch,
useNavigate,
useOutlet,
useOutletContext,
useParams,
useResolvedPath,
useRoutes,
useSearchParams,
useAppData,
useClientLoaderData,
useServerLoaderData,
renderClient,
__getRoot,
Link,
useRouteData,
__useFetcher,
withRouter,
} from '/Users/whyour/resp/qinglong/node_modules/.pnpm/@umijs+renderer-react@4.0.21_ef5jwxihqo6n7gxfmzogljlgcm/node_modules/@umijs/renderer-react';
// umi/client/client/plugin
export {
ApplyPluginsType,
PluginManager,
} from '/Users/whyour/resp/qinglong/node_modules/.pnpm/umi@4.0.21_cuhbl366s6fdg3i7ra7vd4alre/node_modules/umi/client/client/plugin.js';
export { history, createHistory } from './core/history';
export { terminal } from './core/terminal';
// plugins
// plugins types.d.ts
export { defineApp } from './core/defineApp';
export type { RuntimeConfig } from './core/defineApp';
@@ -0,0 +1,29 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
"jsx": "react-jsx",
"esModuleInterop": true,
"sourceMap": true,
"baseUrl": "../../",
"strict": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"paths": {
"@/*": ["src/*"],
"@@/*": ["src/.umi/*"],
"@umijs/max": [
"/Users/whyour/resp/qinglong/node_modules/.pnpm/umi@4.0.21_cuhbl366s6fdg3i7ra7vd4alre/node_modules/umi"
],
"@umijs/max/typings": ["src/.umi/typings"]
}
},
"include": [
"../../.umirc.ts",
"../../**/*.d.ts",
"../../**/*.ts",
"../../**/*.tsx"
]
}
+138
View File
@@ -0,0 +1,138 @@
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
type CSSModuleClasses = { readonly [key: string]: string };
declare module '*.css' {
const classes: CSSModuleClasses;
export default classes;
}
declare module '*.scss' {
const classes: CSSModuleClasses;
export default classes;
}
declare module '*.sass' {
const classes: CSSModuleClasses;
export default classes;
}
declare module '*.less' {
const classes: CSSModuleClasses;
export default classes;
}
declare module '*.styl' {
const classes: CSSModuleClasses;
export default classes;
}
declare module '*.stylus' {
const classes: CSSModuleClasses;
export default classes;
}
// images
declare module '*.jpg' {
const src: string;
export default src;
}
declare module '*.jpeg' {
const src: string;
export default src;
}
declare module '*.png' {
const src: string;
export default src;
}
declare module '*.gif' {
const src: string;
export default src;
}
declare module '*.svg' {
import * as React from 'react';
export const ReactComponent: React.FunctionComponent<
React.SVGProps<SVGSVGElement> & { title?: string }
>;
const src: string;
export default src;
}
declare module '*.ico' {
const src: string;
export default src;
}
declare module '*.webp' {
const src: string;
export default src;
}
declare module '*.avif' {
const src: string;
export default src;
}
// media
declare module '*.mp4' {
const src: string;
export default src;
}
declare module '*.webm' {
const src: string;
export default src;
}
declare module '*.ogg' {
const src: string;
export default src;
}
declare module '*.mp3' {
const src: string;
export default src;
}
declare module '*.wav' {
const src: string;
export default src;
}
declare module '*.flac' {
const src: string;
export default src;
}
declare module '*.aac' {
const src: string;
export default src;
}
// fonts
declare module '*.woff' {
const src: string;
export default src;
}
declare module '*.woff2' {
const src: string;
export default src;
}
declare module '*.eot' {
const src: string;
export default src;
}
declare module '*.ttf' {
const src: string;
export default src;
}
declare module '*.otf' {
const src: string;
export default src;
}
// other
declare module '*.wasm' {
const initWasm: (
options: WebAssembly.Imports,
) => Promise<WebAssembly.Exports>;
export default initWasm;
}
declare module '*.webmanifest' {
const src: string;
export default src;
}
declare module '*.pdf' {
const src: string;
export default src;
}
declare module '*.txt' {
const src: string;
export default src;
}
+60
View File
@@ -0,0 +1,60 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import './core/polyfill';
import 'antd/dist/antd.less';
import { renderClient } from '/Users/whyour/resp/qinglong/node_modules/.pnpm/@umijs+renderer-react@4.0.21_ef5jwxihqo6n7gxfmzogljlgcm/node_modules/@umijs/renderer-react';
import { getRoutes } from './core/route';
import { createPluginManager } from './core/plugin';
import { createHistory } from './core/history';
import Loading from '@/loading';
import { ApplyPluginsType } from 'umi';
const publicPath = '/';
const runtimePublicPath = false;
async function render() {
const pluginManager = createPluginManager();
const { routes, routeComponents } = await getRoutes(pluginManager);
// allow user to extend routes
await pluginManager.applyPlugins({
key: 'patchRoutes',
type: ApplyPluginsType.event,
args: {
routes,
routeComponents,
},
});
return pluginManager.applyPlugins({
key: 'render',
type: ApplyPluginsType.compose,
initialValue() {
const contextOpts = pluginManager.applyPlugins({
key: 'modifyContextOpts',
type: ApplyPluginsType.modify,
initialValue: {},
});
const basename = contextOpts.basename || '/';
const context = {
routes,
routeComponents,
pluginManager,
rootElement: contextOpts.rootElement || document.getElementById('root'),
loadingComponent: Loading,
publicPath,
runtimePublicPath,
history: createHistory({
type: contextOpts.historyType || 'browser',
basename,
...contextOpts.historyOpts,
}),
basename,
};
return renderClient(context);
},
})();
}
render();
@@ -0,0 +1,9 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
import React from 'react';
import { Outlet, useOutletContext } from 'umi';
export default function EmptyRoute() {
const context = useOutletContext();
return <Outlet context={context} />;
}
+21
View File
@@ -0,0 +1,21 @@
// @ts-nocheck
// This file is generated by Umi automatically
// DO NOT CHANGE IT MANUALLY!
interface IDefaultRuntimeConfig {
onRouteChange?: (props: {
routes: any;
clientRoutes: any;
location: any;
action: any;
}) => void;
patchRoutes?: (props: { routes: any }) => void;
patchClientRoutes?: (props: { routes: any }) => void;
render?: (oldRender: () => void) => void;
rootContainer?: (lastRootContainer: JSX.Element, args?: any) => void;
[key: string]: any;
}
export type RuntimeConfig = IDefaultRuntimeConfig;
export function defineApp(config: RuntimeConfig): RuntimeConfig {
return config;
}

Some files were not shown because too many files have changed in this diff Show More