mirror of
https://github.com/whyour/qinglong.git
synced 2026-08-13 04:02:56 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55945e4cd1 | ||
|
|
b39036f8f8 | ||
|
|
f07093d29f | ||
|
|
11c789c71c | ||
|
|
81898f9dd7 | ||
|
|
6dba8ae72d | ||
|
|
c47896e787 | ||
|
|
14cb1f7788 | ||
|
|
892d91edc4 | ||
|
|
74916670eb | ||
|
|
b31eab02d7 | ||
|
|
9c258ab113 | ||
|
|
3bcba11b33 | ||
|
|
15140fd87d | ||
|
|
e83058c3bc | ||
|
|
29f0c2c9ac | ||
|
|
f25fe27473 | ||
|
|
0ae1f284ec | ||
|
|
49c441117a | ||
|
|
7bc5ff01a6 | ||
|
|
8128fb8a9f | ||
|
|
315ae49360 | ||
|
|
35c6475534 | ||
|
|
7f3e60423b | ||
|
|
0a723318a1 | ||
|
|
2c1e7535b8 | ||
|
|
48d1fba699 | ||
|
|
06f861baaf | ||
|
|
bbbd353567 |
@@ -3,55 +3,50 @@ name: Build And Push Docker Image
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- '.github/**'
|
- "*.md"
|
||||||
- '*.md'
|
|
||||||
branches:
|
branches:
|
||||||
- 'master'
|
- "master"
|
||||||
- 'develop'
|
- "develop"
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- "v*"
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '00 20 * * *'
|
- cron: "00 20 * * *"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
to_gitlab:
|
to_gitlab:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: pixta-dev/repository-mirroring-action@v1
|
- uses: pixta-dev/repository-mirroring-action@v1
|
||||||
with:
|
with:
|
||||||
target_repo_url:
|
target_repo_url: git@gitlab.com:whyour/qinglong.git
|
||||||
git@gitlab.com:whyour/qinglong.git
|
ssh_private_key: ${{ secrets.GITLAB_SSH_PK }}
|
||||||
ssh_private_key:
|
|
||||||
${{ secrets.GITLAB_SSH_PK }}
|
|
||||||
|
|
||||||
to_gitee:
|
to_gitee:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: pixta-dev/repository-mirroring-action@v1
|
- uses: pixta-dev/repository-mirroring-action@v1
|
||||||
with:
|
with:
|
||||||
target_repo_url:
|
target_repo_url: git@gitee.com:whyour/qinglong.git
|
||||||
git@gitee.com:whyour/qinglong.git
|
ssh_private_key: ${{ secrets.GITLAB_SSH_PK }}
|
||||||
ssh_private_key:
|
|
||||||
${{ secrets.GITLAB_SSH_PK }}
|
|
||||||
|
|
||||||
build-static:
|
build-static:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v3
|
||||||
with:
|
with:
|
||||||
version: '8.3.1'
|
version: "8.3.1"
|
||||||
|
|
||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: "pnpm"
|
||||||
|
|
||||||
- name: build front and back
|
- name: build front and back
|
||||||
run: |
|
run: |
|
||||||
@@ -83,6 +78,7 @@ jobs:
|
|||||||
export GIT_SSH_COMMAND="ssh -v -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no -l git"
|
export GIT_SSH_COMMAND="ssh -v -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no -l git"
|
||||||
git remote add gitee "${REPO_GITEE}"
|
git remote add gitee "${REPO_GITEE}"
|
||||||
git remote add gitlab "${REPO_GITLAB}"
|
git remote add gitlab "${REPO_GITLAB}"
|
||||||
|
git gc
|
||||||
git push --force --quiet gitee ${GITHUB_BRANCH}:${GITHUB_BRANCH}
|
git push --force --quiet gitee ${GITHUB_BRANCH}:${GITHUB_BRANCH}
|
||||||
git push --force --quiet gitlab ${GITHUB_BRANCH}:${GITHUB_BRANCH}
|
git push --force --quiet gitlab ${GITHUB_BRANCH}:${GITHUB_BRANCH}
|
||||||
|
|
||||||
@@ -99,12 +95,12 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v3
|
||||||
with:
|
with:
|
||||||
version: '8.3.1'
|
version: "8.3.1"
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
cache: 'pnpm'
|
cache: "pnpm"
|
||||||
|
|
||||||
- name: Setup timezone
|
- name: Setup timezone
|
||||||
uses: szenius/set-timezone@v1.2
|
uses: szenius/set-timezone@v1.2
|
||||||
@@ -150,7 +146,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
id: docker_build
|
id: docker_build
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
@@ -169,6 +165,71 @@ jobs:
|
|||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
cache-from: type=registry,ref=whyour/qinglong:cache
|
cache-from: type=registry,ref=whyour/qinglong:cache
|
||||||
cache-to: type=registry,ref=whyour/qinglong:cache,mode=max
|
cache-to: type=registry,ref=whyour/qinglong:cache,mode=max
|
||||||
|
|
||||||
- name: Image digest
|
- name: Image digest
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
run: |
|
||||||
|
echo ${{ steps.docker_build.outputs.digest }}
|
||||||
|
|
||||||
|
build310:
|
||||||
|
if: ${{ github.ref_name == 'master' }}
|
||||||
|
needs: build-static
|
||||||
|
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: pnpm/action-setup@v3
|
||||||
|
with:
|
||||||
|
version: "8.3.1"
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
cache: "pnpm"
|
||||||
|
|
||||||
|
- name: Setup timezone
|
||||||
|
uses: szenius/set-timezone@v1.2
|
||||||
|
with:
|
||||||
|
timezoneLinux: Asia/Shanghai
|
||||||
|
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Login to GHCR
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Build and push python3.10
|
||||||
|
id: docker_build_310
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
build-args: |
|
||||||
|
MAINTAINER=${{ github.repository_owner }}
|
||||||
|
QL_BRANCH=${{ github.ref_name }}
|
||||||
|
SOURCE_COMMIT=${{ github.sha }}
|
||||||
|
network: host
|
||||||
|
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/ppc64le,linux/s390x,linux/386
|
||||||
|
context: .
|
||||||
|
file: ./docker/310.Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: whyour/qinglong:python3.10
|
||||||
|
cache-from: type=registry,ref=whyour/qinglong:cache-python3.10
|
||||||
|
cache-to: type=registry,ref=whyour/qinglong:cache-python3.10,mode=max
|
||||||
|
|
||||||
|
- name: Image digest
|
||||||
|
run: |
|
||||||
|
echo ${{ steps.docker_build_310.outputs.digest }}
|
||||||
|
|||||||
+9
-1
@@ -166,6 +166,14 @@ podman run -dit \
|
|||||||
It is recommended to use a pure system installation to avoid losing the original system data, you need to install node/npm/python3/pip3 yourself
|
It is recommended to use a pure system installation to avoid losing the original system data, you need to install node/npm/python3/pip3 yourself
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Debian/Ubuntu
|
||||||
|
curl -sL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
||||||
|
# Centos
|
||||||
|
curl --silent --location https://rpm.nodesource.com/setup_20.x | sudo bash
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install -g node-pre-gyp pnpm@8.3.1
|
||||||
npm install -g @whyour/qinglong
|
npm install -g @whyour/qinglong
|
||||||
qinglong
|
qinglong
|
||||||
# Add the environment variables QL_DIR and QL_DATA_DIR when prompted
|
# Add the environment variables QL_DIR and QL_DATA_DIR when prompted
|
||||||
@@ -178,7 +186,7 @@ qinglong
|
|||||||
## Development
|
## Development
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ git clone git@github.com:whyour/qinglong.git
|
$ git clone https://github.com/whyour/qinglong.git
|
||||||
$ cd qinglong
|
$ cd qinglong
|
||||||
$ cp .env.example .env
|
$ cp .env.example .env
|
||||||
# Recommended use pnpm https://pnpm.io/zh/installation
|
# Recommended use pnpm https://pnpm.io/zh/installation
|
||||||
|
|||||||
@@ -166,6 +166,14 @@ podman run -dit \
|
|||||||
建议使用纯净系统安装,避免系统原有数据丢失,需要自己安装 node/npm/python3/pip3
|
建议使用纯净系统安装,避免系统原有数据丢失,需要自己安装 node/npm/python3/pip3
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Debian/Ubuntu
|
||||||
|
curl -sL https://deb.nodesource.com/setup_20.x | sudo -E bash -
|
||||||
|
# Centos
|
||||||
|
curl --silent --location https://rpm.nodesource.com/setup_20.x | sudo bash
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install -g node-pre-gyp pnpm@8.3.1
|
||||||
npm install -g @whyour/qinglong
|
npm install -g @whyour/qinglong
|
||||||
qinglong
|
qinglong
|
||||||
# 根据提示增加环境变量 QL_DIR 和 QL_DATA_DIR
|
# 根据提示增加环境变量 QL_DIR 和 QL_DATA_DIR
|
||||||
@@ -178,7 +186,7 @@ qinglong
|
|||||||
## 开发
|
## 开发
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ git clone git@github.com:whyour/qinglong.git
|
$ git clone https://github.com/whyour/qinglong.git
|
||||||
$ cd qinglong
|
$ cd qinglong
|
||||||
$ cp .env.example .env
|
$ cp .env.example .env
|
||||||
# 推荐使用 pnpm https://pnpm.io/zh/installation
|
# 推荐使用 pnpm https://pnpm.io/zh/installation
|
||||||
|
|||||||
+19
-19
@@ -7,7 +7,7 @@ import * as fs from 'fs/promises';
|
|||||||
import { celebrate, Joi } from 'celebrate';
|
import { celebrate, Joi } from 'celebrate';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { SAMPLE_FILES } from '../config/const';
|
import { SAMPLE_FILES } from '../config/const';
|
||||||
import got from 'got';
|
import ConfigService from '../services/config';
|
||||||
const route = Router();
|
const route = Router();
|
||||||
|
|
||||||
export default (app: Router) => {
|
export default (app: Router) => {
|
||||||
@@ -50,24 +50,9 @@ export default (app: Router) => {
|
|||||||
route.get(
|
route.get(
|
||||||
'/detail',
|
'/detail',
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const logger: Logger = Container.get('logger');
|
|
||||||
try {
|
try {
|
||||||
let content = '';
|
const configService = Container.get(ConfigService);
|
||||||
const _path = req.query.path as string;
|
await configService.getFile(req.query.path as string, res);
|
||||||
if (config.blackFileList.includes(_path) || !_path) {
|
|
||||||
res.send({ code: 403, message: '文件无法访问' });
|
|
||||||
}
|
|
||||||
if (_path.startsWith('sample/')) {
|
|
||||||
const res = await got.get(
|
|
||||||
`https://gitlab.com/whyour/qinglong/-/raw/master/${_path}`,
|
|
||||||
);
|
|
||||||
content = res.body;
|
|
||||||
} else if (_path.startsWith('data/scripts/')) {
|
|
||||||
content = await getFileContentByName(join(config.rootPath, _path));
|
|
||||||
} else {
|
|
||||||
content = await getFileContentByName(join(config.configPath, _path));
|
|
||||||
}
|
|
||||||
res.send({ code: 200, data: content });
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
@@ -89,7 +74,10 @@ export default (app: Router) => {
|
|||||||
if (config.blackFileList.includes(name)) {
|
if (config.blackFileList.includes(name)) {
|
||||||
res.send({ code: 403, message: '文件无法访问' });
|
res.send({ code: 403, message: '文件无法访问' });
|
||||||
}
|
}
|
||||||
const path = join(config.configPath, name);
|
let path = join(config.configPath, name);
|
||||||
|
if (name.startsWith('data/scripts/')) {
|
||||||
|
path = join(config.rootPath, name);
|
||||||
|
}
|
||||||
await fs.writeFile(path, content);
|
await fs.writeFile(path, content);
|
||||||
res.send({ code: 200, message: '保存成功' });
|
res.send({ code: 200, message: '保存成功' });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -97,4 +85,16 @@ export default (app: Router) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
route.get(
|
||||||
|
'/:file',
|
||||||
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
try {
|
||||||
|
const configService = Container.get(ConfigService);
|
||||||
|
await configService.getFile(req.params.file, res);
|
||||||
|
} catch (e) {
|
||||||
|
return next(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -134,4 +134,20 @@ export default (app: Router) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
route.put(
|
||||||
|
'/cancel',
|
||||||
|
celebrate({
|
||||||
|
body: Joi.array().items(Joi.number().required()),
|
||||||
|
}),
|
||||||
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
try {
|
||||||
|
const dependenceService = Container.get(DependenceService);
|
||||||
|
await dependenceService.cancel(req.body);
|
||||||
|
return res.send({ code: 200 });
|
||||||
|
} catch (e) {
|
||||||
|
return next(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
+20
-1
@@ -26,10 +26,29 @@ export default (app: Router) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
route.get(
|
||||||
|
'/detail',
|
||||||
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
try {
|
||||||
|
if (blacklist.includes(req.path)) {
|
||||||
|
return res.send({ code: 403, message: '暂无权限' });
|
||||||
|
}
|
||||||
|
const filePath = join(
|
||||||
|
config.logPath,
|
||||||
|
(req.query.path || '') as string,
|
||||||
|
req.query.file as string,
|
||||||
|
);
|
||||||
|
const content = await getFileContentByName(filePath);
|
||||||
|
res.send({ code: 200, data: content });
|
||||||
|
} catch (e) {
|
||||||
|
return next(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
route.get(
|
route.get(
|
||||||
'/:file',
|
'/:file',
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const logger: Logger = Container.get('logger');
|
|
||||||
try {
|
try {
|
||||||
if (blacklist.includes(req.path)) {
|
if (blacklist.includes(req.path)) {
|
||||||
return res.send({ code: 403, message: '暂无权限' });
|
return res.send({ code: 403, message: '暂无权限' });
|
||||||
|
|||||||
+18
-4
@@ -72,17 +72,31 @@ export default (app: Router) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
route.get(
|
||||||
|
'/detail',
|
||||||
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
try {
|
||||||
|
const scriptService = Container.get(ScriptService);
|
||||||
|
const content = await scriptService.getFile(
|
||||||
|
req.query.path as string,
|
||||||
|
req.query.file as string,
|
||||||
|
);
|
||||||
|
res.send({ code: 200, data: content });
|
||||||
|
} catch (e) {
|
||||||
|
return next(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
route.get(
|
route.get(
|
||||||
'/:file',
|
'/:file',
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const logger: Logger = Container.get('logger');
|
|
||||||
try {
|
try {
|
||||||
const filePath = join(
|
const scriptService = Container.get(ScriptService);
|
||||||
config.scriptPath,
|
const content = await scriptService.getFile(
|
||||||
req.query.path as string,
|
req.query.path as string,
|
||||||
req.params.file,
|
req.params.file,
|
||||||
);
|
);
|
||||||
const content = await getFileContentByName(filePath);
|
|
||||||
res.send({ code: 200, data: content });
|
res.send({ code: 200, data: content });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return next(e);
|
return next(e);
|
||||||
|
|||||||
+1
-1
@@ -216,7 +216,7 @@ export default (app: Router) => {
|
|||||||
'/reload',
|
'/reload',
|
||||||
celebrate({
|
celebrate({
|
||||||
body: Joi.object({
|
body: Joi.object({
|
||||||
type: Joi.string().required(),
|
type: Joi.string().optional().allow('').allow(null),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
|||||||
@@ -74,6 +74,9 @@ export default (app: Router) => {
|
|||||||
async (req: Request, res: Response, next: NextFunction) => {
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
const logger: Logger = Container.get('logger');
|
const logger: Logger = Container.get('logger');
|
||||||
try {
|
try {
|
||||||
|
if (process.env.DeployEnv === 'demo') {
|
||||||
|
return res.send({ code: 450, message: '未知错误' });
|
||||||
|
}
|
||||||
const userService = Container.get(UserService);
|
const userService = Container.get(UserService);
|
||||||
await userService.updateUsernameAndPassword(req.body);
|
await userService.updateUsernameAndPassword(req.body);
|
||||||
res.send({ code: 200, message: '更新成功' });
|
res.send({ code: 200, message: '更新成功' });
|
||||||
|
|||||||
+28
-24
@@ -360,6 +360,31 @@ export function parseHeaders(headers: string) {
|
|||||||
return parsed;
|
return parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseString(input: string): Record<string, string> {
|
||||||
|
const regex = /(\w+):\s*((?:(?!\n\w+:).)*)/g;
|
||||||
|
const matches: Record<string, string> = {};
|
||||||
|
|
||||||
|
let match;
|
||||||
|
while ((match = regex.exec(input)) !== null) {
|
||||||
|
const [, key, value] = match;
|
||||||
|
const _key = key.trim();
|
||||||
|
if (!_key || matches[_key]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _value = value.trim();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const jsonValue = JSON.parse(_value);
|
||||||
|
matches[_key] = jsonValue;
|
||||||
|
} catch (error) {
|
||||||
|
matches[_key] = _value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
export function parseBody(
|
export function parseBody(
|
||||||
body: string,
|
body: string,
|
||||||
contentType:
|
contentType:
|
||||||
@@ -372,28 +397,7 @@ export function parseBody(
|
|||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsed: any = {};
|
const parsed = parseString(body);
|
||||||
let key;
|
|
||||||
let val;
|
|
||||||
let i;
|
|
||||||
|
|
||||||
body &&
|
|
||||||
body.split('\n').forEach(function parser(line) {
|
|
||||||
i = line.indexOf(':');
|
|
||||||
key = line.substring(0, i).trim();
|
|
||||||
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) {
|
switch (contentType) {
|
||||||
case 'multipart/form-data':
|
case 'multipart/form-data':
|
||||||
@@ -435,8 +439,8 @@ export async function killTask(pid: number) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getPid(name: string) {
|
export async function getPid(cmd: string) {
|
||||||
const taskCommand = `ps -eo pid,command | grep "${name}" | grep -v grep | awk '{print $1}' | head -1 | xargs echo -n`;
|
const taskCommand = `ps -eo pid,command | grep "${cmd}" | grep -v grep | awk '{print $1}' | head -1 | xargs echo -n`;
|
||||||
const pid = await promiseExec(taskCommand);
|
const pid = await promiseExec(taskCommand);
|
||||||
return pid ? Number(pid) : undefined;
|
return pid ? Number(pid) : undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ export enum DependenceStatus {
|
|||||||
'removed',
|
'removed',
|
||||||
'removeFailed',
|
'removeFailed',
|
||||||
'queued',
|
'queued',
|
||||||
|
'cancelled',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DependenceTypes {
|
export enum DependenceTypes {
|
||||||
|
|||||||
+46
-16
@@ -10,11 +10,57 @@ import config from '../config';
|
|||||||
import { CrontabViewModel, CronViewType } from '../data/cronView';
|
import { CrontabViewModel, CronViewType } from '../data/cronView';
|
||||||
import { initPosition } from '../data/env';
|
import { initPosition } from '../data/env';
|
||||||
import { AuthDataType, SystemModel } from '../data/system';
|
import { AuthDataType, SystemModel } from '../data/system';
|
||||||
|
import SystemService from '../services/system';
|
||||||
|
|
||||||
export default async () => {
|
export default async () => {
|
||||||
const cronService = Container.get(CronService);
|
const cronService = Container.get(CronService);
|
||||||
const envService = Container.get(EnvService);
|
const envService = Container.get(EnvService);
|
||||||
const dependenceService = Container.get(DependenceService);
|
const dependenceService = Container.get(DependenceService);
|
||||||
|
const systemService = Container.get(SystemService);
|
||||||
|
|
||||||
|
const installDependencies = () => {
|
||||||
|
// 初始化时安装所有处于安装中,安装成功,安装失败的依赖
|
||||||
|
DependenceModel.findAll({
|
||||||
|
where: {},
|
||||||
|
order: [
|
||||||
|
['type', 'DESC'],
|
||||||
|
['createdAt', 'DESC'],
|
||||||
|
],
|
||||||
|
raw: true,
|
||||||
|
}).then(async (docs) => {
|
||||||
|
await DependenceModel.update(
|
||||||
|
{ status: DependenceStatus.queued, log: [] },
|
||||||
|
{ where: { id: docs.map((x) => x.id!) } },
|
||||||
|
);
|
||||||
|
setTimeout(() => {
|
||||||
|
dependenceService.installDependenceOneByOne(docs);
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 初始化更新 linux/python/nodejs 镜像源配置
|
||||||
|
const systemConfig = await systemService.getSystemConfig();
|
||||||
|
if (systemConfig.info?.pythonMirror) {
|
||||||
|
systemService.updatePythonMirror({
|
||||||
|
pythonMirror: systemConfig.info?.pythonMirror,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (systemConfig.info?.linuxMirror) {
|
||||||
|
systemService.updateLinuxMirror(
|
||||||
|
{
|
||||||
|
linuxMirror: systemConfig.info?.linuxMirror,
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
() => installDependencies(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
installDependencies();
|
||||||
|
}
|
||||||
|
if (systemConfig.info?.nodeMirror) {
|
||||||
|
systemService.updateNodeMirror({
|
||||||
|
nodeMirror: systemConfig.info?.nodeMirror,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化新增默认全部任务视图
|
// 初始化新增默认全部任务视图
|
||||||
CrontabViewModel.findAll({
|
CrontabViewModel.findAll({
|
||||||
@@ -33,22 +79,6 @@ export default async () => {
|
|||||||
// 初始化更新所有任务状态为空闲
|
// 初始化更新所有任务状态为空闲
|
||||||
await CrontabModel.update({ status: CrontabStatus.idle }, { where: {} });
|
await CrontabModel.update({ status: CrontabStatus.idle }, { where: {} });
|
||||||
|
|
||||||
// 初始化时安装所有处于安装中,安装成功,安装失败的依赖
|
|
||||||
DependenceModel.findAll({
|
|
||||||
where: {},
|
|
||||||
order: [
|
|
||||||
['type', 'DESC'],
|
|
||||||
['createdAt', 'DESC'],
|
|
||||||
],
|
|
||||||
raw: true,
|
|
||||||
}).then(async (docs) => {
|
|
||||||
await DependenceModel.update(
|
|
||||||
{ status: DependenceStatus.queued, log: [] },
|
|
||||||
{ where: { id: docs.map((x) => x.id!) } },
|
|
||||||
);
|
|
||||||
dependenceService.installDependenceOneByOne(docs);
|
|
||||||
});
|
|
||||||
|
|
||||||
// 初始化时执行一次所有的 ql repo 任务
|
// 初始化时执行一次所有的 ql repo 任务
|
||||||
CrontabModel.findAll({
|
CrontabModel.findAll({
|
||||||
where: {
|
where: {
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { Service, Inject } from 'typedi';
|
||||||
|
import path, { join } from 'path';
|
||||||
|
import config from '../config';
|
||||||
|
import { getFileContentByName } from '../config/util';
|
||||||
|
import { Response } from 'express';
|
||||||
|
import got from 'got';
|
||||||
|
|
||||||
|
@Service()
|
||||||
|
export default class ConfigService {
|
||||||
|
constructor() {}
|
||||||
|
|
||||||
|
public async getFile(filePath: string, res: Response) {
|
||||||
|
let content = '';
|
||||||
|
if (config.blackFileList.includes(filePath) || !filePath) {
|
||||||
|
res.send({ code: 403, message: '文件无法访问' });
|
||||||
|
}
|
||||||
|
if (filePath.startsWith('sample/')) {
|
||||||
|
const res = await got.get(
|
||||||
|
`https://gitlab.com/whyour/qinglong/-/raw/master/${filePath}`,
|
||||||
|
);
|
||||||
|
content = res.body;
|
||||||
|
} else if (filePath.startsWith('data/scripts/')) {
|
||||||
|
content = await getFileContentByName(join(config.rootPath, filePath));
|
||||||
|
} else {
|
||||||
|
content = await getFileContentByName(join(config.configPath, filePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
res.send({ code: 200, data: content });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,12 @@ import {
|
|||||||
import { spawn } from 'cross-spawn';
|
import { spawn } from 'cross-spawn';
|
||||||
import SockService from './sock';
|
import SockService from './sock';
|
||||||
import { FindOptions, Op } from 'sequelize';
|
import { FindOptions, Op } from 'sequelize';
|
||||||
import { fileExist, promiseExecSuccess } from '../config/util';
|
import {
|
||||||
|
fileExist,
|
||||||
|
getPid,
|
||||||
|
killTask,
|
||||||
|
promiseExecSuccess,
|
||||||
|
} from '../config/util';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import taskLimit from '../shared/pLimit';
|
import taskLimit from '../shared/pLimit';
|
||||||
|
|
||||||
@@ -86,11 +91,21 @@ export default class DependenceService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async dependencies(
|
public async dependencies(
|
||||||
{ searchValue, type }: { searchValue: string; type: string },
|
{
|
||||||
sort: any = { position: -1 },
|
searchValue,
|
||||||
|
type,
|
||||||
|
status,
|
||||||
|
}: { searchValue: string; type: string; status: string },
|
||||||
|
sort: any = [],
|
||||||
query: any = {},
|
query: any = {},
|
||||||
): Promise<Dependence[]> {
|
): Promise<Dependence[]> {
|
||||||
let condition = { ...query, type: DependenceTypes[type as any] };
|
let condition = {
|
||||||
|
...query,
|
||||||
|
type: DependenceTypes[type as any],
|
||||||
|
};
|
||||||
|
if (status) {
|
||||||
|
condition.status = status.split(',').map(Number);
|
||||||
|
}
|
||||||
if (searchValue) {
|
if (searchValue) {
|
||||||
const encodeText = encodeURI(searchValue);
|
const encodeText = encodeURI(searchValue);
|
||||||
const reg = {
|
const reg = {
|
||||||
@@ -106,7 +121,7 @@ export default class DependenceService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const result = await this.find(condition);
|
const result = await this.find(condition, sort);
|
||||||
return result as any;
|
return result as any;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error;
|
throw error;
|
||||||
@@ -134,6 +149,28 @@ export default class DependenceService {
|
|||||||
return docs;
|
return docs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async cancel(ids: number[]) {
|
||||||
|
const docs = await DependenceModel.findAll({ where: { id: ids } });
|
||||||
|
for (const doc of docs) {
|
||||||
|
taskLimit.removeQueuedDependency(doc);
|
||||||
|
const depInstallCommand = InstallDependenceCommandTypes[doc.type];
|
||||||
|
const depUnInstallCommand = unInstallDependenceCommandTypes[doc.type];
|
||||||
|
const installCmd = `${depInstallCommand} ${doc.name.trim()}`;
|
||||||
|
const unInstallCmd = `${depUnInstallCommand} ${doc.name.trim()}`;
|
||||||
|
const pids = await Promise.all([
|
||||||
|
getPid(installCmd),
|
||||||
|
getPid(unInstallCmd),
|
||||||
|
]);
|
||||||
|
for (const pid of pids) {
|
||||||
|
pid && (await killTask(pid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await DependenceModel.update(
|
||||||
|
{ status: DependenceStatus.cancelled },
|
||||||
|
{ where: { id: ids } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private async find(query: any, sort: any = []): Promise<Dependence[]> {
|
private async find(query: any, sort: any = []): Promise<Dependence[]> {
|
||||||
const docs = await DependenceModel.findAll({
|
const docs = await DependenceModel.findAll({
|
||||||
where: { ...query },
|
where: { ...query },
|
||||||
@@ -168,8 +205,14 @@ export default class DependenceService {
|
|||||||
isInstall: boolean = true,
|
isInstall: boolean = true,
|
||||||
force: boolean = false,
|
force: boolean = false,
|
||||||
) {
|
) {
|
||||||
return taskLimit.runOneByOne(() => {
|
return taskLimit.runDependeny(dependency, () => {
|
||||||
return new Promise(async (resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
|
if (taskLimit.firstDependencyId !== dependency.id) {
|
||||||
|
return resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
taskLimit.removeQueuedDependency(dependency);
|
||||||
|
|
||||||
const depIds = [dependency.id!];
|
const depIds = [dependency.id!];
|
||||||
const status = isInstall
|
const status = isInstall
|
||||||
? DependenceStatus.installing
|
? DependenceStatus.installing
|
||||||
@@ -317,7 +360,17 @@ export default class DependenceService {
|
|||||||
? DependenceStatus.installFailed
|
? DependenceStatus.installFailed
|
||||||
: DependenceStatus.removeFailed;
|
: DependenceStatus.removeFailed;
|
||||||
}
|
}
|
||||||
await DependenceModel.update({ status }, { where: { id: depIds } });
|
const docs = await DependenceModel.findAll({ where: { id: depIds } });
|
||||||
|
const _docIds = docs
|
||||||
|
.filter((x) => x.status !== DependenceStatus.cancelled)
|
||||||
|
.map((x) => x.id!);
|
||||||
|
|
||||||
|
if (_docIds.length > 0) {
|
||||||
|
await DependenceModel.update(
|
||||||
|
{ status },
|
||||||
|
{ where: { id: _docIds } },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// 如果删除依赖成功或者强制删除
|
// 如果删除依赖成功或者强制删除
|
||||||
if ((isSucceed || force) && !isInstall) {
|
if ((isSucceed || force) && !isInstall) {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { Service, Inject } from 'typedi';
|
import { Service, Inject } from 'typedi';
|
||||||
import winston from 'winston';
|
import winston from 'winston';
|
||||||
import path from 'path';
|
import path, { join } from 'path';
|
||||||
import SockService from './sock';
|
import SockService from './sock';
|
||||||
import CronService from './cron';
|
import CronService from './cron';
|
||||||
import ScheduleService, { TaskCallbacks } from './schedule';
|
import ScheduleService, { TaskCallbacks } from './schedule';
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
import { TASK_COMMAND } from '../config/const';
|
import { TASK_COMMAND } from '../config/const';
|
||||||
import { getPid, killTask, rmPath } from '../config/util';
|
import { getFileContentByName, getPid, killTask, rmPath } from '../config/util';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class ScriptService {
|
export default class ScriptService {
|
||||||
@@ -61,4 +61,10 @@ export default class ScriptService {
|
|||||||
|
|
||||||
return { code: 200 };
|
return { code: 200 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getFile(filePath: string, fileName: string) {
|
||||||
|
const _filePath = join(config.scriptPath, filePath, fileName);
|
||||||
|
const content = await getFileContentByName(_filePath);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-9
@@ -29,6 +29,7 @@ import tar from 'tar';
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import sum from 'lodash/sum';
|
import sum from 'lodash/sum';
|
||||||
|
import { DependenceModel, DependenceStatus, DependenceTypes } from '../data/dependence';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class SystemService {
|
export default class SystemService {
|
||||||
@@ -126,7 +127,7 @@ export default class SystemService {
|
|||||||
return { code: 200, data: info };
|
return { code: 200, data: info };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateNodeMirror(info: SystemModelInfo, res: Response) {
|
public async updateNodeMirror(info: SystemModelInfo, res?: Response) {
|
||||||
const oDoc = await this.getSystemConfig();
|
const oDoc = await this.getSystemConfig();
|
||||||
await this.updateAuthDb({
|
await this.updateAuthDb({
|
||||||
...oDoc,
|
...oDoc,
|
||||||
@@ -136,13 +137,19 @@ export default class SystemService {
|
|||||||
if (info.nodeMirror) {
|
if (info.nodeMirror) {
|
||||||
cmd = `pnpm config set registry ${info.nodeMirror}`;
|
cmd = `pnpm config set registry ${info.nodeMirror}`;
|
||||||
}
|
}
|
||||||
const command = `cd && ${cmd} && pnpm i -g`;
|
let command = `cd && ${cmd}`;
|
||||||
|
const docs = await DependenceModel.findAll({
|
||||||
|
where: { type: DependenceTypes.nodejs, status: DependenceStatus.installed },
|
||||||
|
});
|
||||||
|
if (docs.length > 0) {
|
||||||
|
command += ` && pnpm i -g`;
|
||||||
|
}
|
||||||
this.scheduleService.runTask(
|
this.scheduleService.runTask(
|
||||||
command,
|
command,
|
||||||
{
|
{
|
||||||
onStart: async (cp) => {
|
onStart: async (cp) => {
|
||||||
res.setHeader('QL-Task-Pid', `${cp.pid}`);
|
res?.setHeader('QL-Task-Pid', `${cp.pid}`);
|
||||||
res.end();
|
res?.end();
|
||||||
},
|
},
|
||||||
onEnd: async () => {
|
onEnd: async () => {
|
||||||
this.sockService.sendMessage({
|
this.sockService.sendMessage({
|
||||||
@@ -177,7 +184,11 @@ export default class SystemService {
|
|||||||
return { code: 200, data: info };
|
return { code: 200, data: info };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateLinuxMirror(info: SystemModelInfo, res: Response) {
|
public async updateLinuxMirror(
|
||||||
|
info: SystemModelInfo,
|
||||||
|
res?: Response,
|
||||||
|
onEnd?: () => void,
|
||||||
|
) {
|
||||||
const oDoc = await this.getSystemConfig();
|
const oDoc = await this.getSystemConfig();
|
||||||
await this.updateAuthDb({
|
await this.updateAuthDb({
|
||||||
...oDoc,
|
...oDoc,
|
||||||
@@ -185,8 +196,12 @@ export default class SystemService {
|
|||||||
});
|
});
|
||||||
let defaultDomain = 'https://dl-cdn.alpinelinux.org';
|
let defaultDomain = 'https://dl-cdn.alpinelinux.org';
|
||||||
let targetDomain = 'https://dl-cdn.alpinelinux.org';
|
let targetDomain = 'https://dl-cdn.alpinelinux.org';
|
||||||
if (oDoc.info?.linuxMirror) {
|
const content = await fs.promises.readFile('/etc/apk/repositories', {
|
||||||
defaultDomain = oDoc.info.linuxMirror;
|
encoding: 'utf-8',
|
||||||
|
});
|
||||||
|
const domainMatch = content.match(/(http.*)\/alpine\/.*/);
|
||||||
|
if (domainMatch) {
|
||||||
|
defaultDomain = domainMatch[1];
|
||||||
}
|
}
|
||||||
if (info.linuxMirror) {
|
if (info.linuxMirror) {
|
||||||
targetDomain = info.linuxMirror;
|
targetDomain = info.linuxMirror;
|
||||||
@@ -203,14 +218,15 @@ export default class SystemService {
|
|||||||
command,
|
command,
|
||||||
{
|
{
|
||||||
onStart: async (cp) => {
|
onStart: async (cp) => {
|
||||||
res.setHeader('QL-Task-Pid', `${cp.pid}`);
|
res?.setHeader('QL-Task-Pid', `${cp.pid}`);
|
||||||
res.end();
|
res?.end();
|
||||||
},
|
},
|
||||||
onEnd: async () => {
|
onEnd: async () => {
|
||||||
this.sockService.sendMessage({
|
this.sockService.sendMessage({
|
||||||
type: 'updateLinuxMirror',
|
type: 'updateLinuxMirror',
|
||||||
message: 'update linux mirror end',
|
message: 'update linux mirror end',
|
||||||
});
|
});
|
||||||
|
onEnd?.();
|
||||||
},
|
},
|
||||||
onError: async (message: string) => {
|
onError: async (message: string) => {
|
||||||
this.sockService.sendMessage({ type: 'updateLinuxMirror', message });
|
this.sockService.sendMessage({ type: 'updateLinuxMirror', message });
|
||||||
|
|||||||
+46
-20
@@ -2,11 +2,19 @@ import PQueue, { QueueAddOptions } from 'p-queue-cjs';
|
|||||||
import os from 'os';
|
import os from 'os';
|
||||||
import { AuthDataType, SystemModel } from '../data/system';
|
import { AuthDataType, SystemModel } from '../data/system';
|
||||||
import Logger from '../loaders/logger';
|
import Logger from '../loaders/logger';
|
||||||
|
import { Dependence } from '../data/dependence';
|
||||||
|
|
||||||
|
interface IDependencyFn<T> {
|
||||||
|
(): Promise<T>;
|
||||||
|
dependency?: Dependence;
|
||||||
|
}
|
||||||
class TaskLimit {
|
class TaskLimit {
|
||||||
private oneLimit = new PQueue({ concurrency: 1 });
|
private dependenyLimit = new PQueue({ concurrency: 1 });
|
||||||
|
private queuedDependencyIds = new Set<number>([]);
|
||||||
private updateLogLimit = new PQueue({ concurrency: 1 });
|
private updateLogLimit = new PQueue({ concurrency: 1 });
|
||||||
private cronLimit = new PQueue({ concurrency: Math.max(os.cpus().length, 4) });
|
private cronLimit = new PQueue({
|
||||||
|
concurrency: Math.max(os.cpus().length, 4),
|
||||||
|
});
|
||||||
|
|
||||||
get cronLimitActiveCount() {
|
get cronLimitActiveCount() {
|
||||||
return this.cronLimit.pending;
|
return this.cronLimit.pending;
|
||||||
@@ -16,6 +24,10 @@ class TaskLimit {
|
|||||||
return this.cronLimit.size;
|
return this.cronLimit.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get firstDependencyId() {
|
||||||
|
return [...this.queuedDependencyIds.values()][0];
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.setCustomLimit();
|
this.setCustomLimit();
|
||||||
this.handleEvents();
|
this.handleEvents();
|
||||||
@@ -26,21 +38,19 @@ class TaskLimit {
|
|||||||
Logger.info(
|
Logger.info(
|
||||||
`[schedule][任务加入队列] 运行中任务数: ${this.cronLimitActiveCount}, 等待中任务数: ${this.cronLimitPendingCount}`,
|
`[schedule][任务加入队列] 运行中任务数: ${this.cronLimitActiveCount}, 等待中任务数: ${this.cronLimitPendingCount}`,
|
||||||
);
|
);
|
||||||
})
|
});
|
||||||
this.cronLimit.on('active', () => {
|
this.cronLimit.on('active', () => {
|
||||||
Logger.info(
|
Logger.info(
|
||||||
`[schedule][开始处理任务] 运行中任务数: ${this.cronLimitActiveCount + 1}, 等待中任务数: ${this.cronLimitPendingCount}`,
|
`[schedule][开始处理任务] 运行中任务数: ${
|
||||||
);
|
this.cronLimitActiveCount + 1
|
||||||
})
|
}, 等待中任务数: ${this.cronLimitPendingCount}`,
|
||||||
this.cronLimit.on('completed', (param) => {
|
|
||||||
Logger.info(
|
|
||||||
`[schedule][任务处理成功] 参数 ${JSON.stringify(param)}`,
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
this.cronLimit.on('error', error => {
|
this.cronLimit.on('completed', (param) => {
|
||||||
Logger.error(
|
Logger.info(`[schedule][任务处理成功] 参数 ${JSON.stringify(param)}`);
|
||||||
`[schedule][任务处理错误] 参数 ${JSON.stringify(error)}`,
|
});
|
||||||
);
|
this.cronLimit.on('error', (error) => {
|
||||||
|
Logger.error(`[schedule][任务处理错误] 参数 ${JSON.stringify(error)}`);
|
||||||
});
|
});
|
||||||
this.cronLimit.on('next', () => {
|
this.cronLimit.on('next', () => {
|
||||||
Logger.info(
|
Logger.info(
|
||||||
@@ -48,12 +58,16 @@ class TaskLimit {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
this.cronLimit.on('idle', () => {
|
this.cronLimit.on('idle', () => {
|
||||||
Logger.info(
|
Logger.info(`[schedule][任务队列] 空闲中...`);
|
||||||
`[schedule][任务队列] 空闲中...`,
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public removeQueuedDependency(dependency: Dependence) {
|
||||||
|
if (this.queuedDependencyIds.has(dependency.id!)) {
|
||||||
|
this.queuedDependencyIds.delete(dependency.id!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async setCustomLimit(limit?: number) {
|
public async setCustomLimit(limit?: number) {
|
||||||
if (limit) {
|
if (limit) {
|
||||||
this.cronLimit.concurrency = limit;
|
this.cronLimit.concurrency = limit;
|
||||||
@@ -68,15 +82,27 @@ class TaskLimit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async runWithCronLimit<T>(fn: () => Promise<T>, options?: Partial<QueueAddOptions>): Promise<T | void> {
|
public async runWithCronLimit<T>(
|
||||||
|
fn: () => Promise<T>,
|
||||||
|
options?: Partial<QueueAddOptions>,
|
||||||
|
): Promise<T | void> {
|
||||||
return this.cronLimit.add(fn, options);
|
return this.cronLimit.add(fn, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public runOneByOne<T>(fn: () => Promise<T>, options?: Partial<QueueAddOptions>): Promise<T | void> {
|
public runDependeny<T>(
|
||||||
return this.oneLimit.add(fn, options);
|
dependency: Dependence,
|
||||||
|
fn: IDependencyFn<T>,
|
||||||
|
options?: Partial<QueueAddOptions>,
|
||||||
|
): Promise<T | void> {
|
||||||
|
this.queuedDependencyIds.add(dependency.id!);
|
||||||
|
fn.dependency = dependency;
|
||||||
|
return this.dependenyLimit.add(fn, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public updateDepLog<T>(fn: () => Promise<T>, options?: Partial<QueueAddOptions>): Promise<T | void> {
|
public updateDepLog<T>(
|
||||||
|
fn: () => Promise<T>,
|
||||||
|
options?: Partial<QueueAddOptions>,
|
||||||
|
): Promise<T | void> {
|
||||||
return this.updateLogLimit.add(fn, options);
|
return this.updateLogLimit.add(fn, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
FROM python:3.10-alpine3.18 as builder
|
||||||
|
COPY package.json .npmrc pnpm-lock.yaml /tmp/build/
|
||||||
|
RUN set -x \
|
||||||
|
&& apk update \
|
||||||
|
&& apk add nodejs npm git \
|
||||||
|
&& npm i -g pnpm@8.3.1 \
|
||||||
|
&& cd /tmp/build \
|
||||||
|
&& pnpm install --prod
|
||||||
|
|
||||||
|
FROM python:3.10-alpine3.18
|
||||||
|
|
||||||
|
ARG QL_MAINTAINER="whyour"
|
||||||
|
LABEL maintainer="${QL_MAINTAINER}"
|
||||||
|
ARG QL_URL=https://github.com/${QL_MAINTAINER}/qinglong.git
|
||||||
|
ARG QL_BRANCH=develop
|
||||||
|
|
||||||
|
ENV PNPM_HOME=/root/.local/share/pnpm \
|
||||||
|
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/.local/share/pnpm:/root/.local/share/pnpm/global/5/node_modules:$PNPM_HOME \
|
||||||
|
NODE_PATH=/usr/local/bin:/usr/local/pnpm-global/5/node_modules:/usr/local/lib/node_modules:/root/.local/share/pnpm/global/5/node_modules \
|
||||||
|
LANG=C.UTF-8 \
|
||||||
|
SHELL=/bin/bash \
|
||||||
|
PS1="\u@\h:\w \$ " \
|
||||||
|
QL_DIR=/ql \
|
||||||
|
QL_BRANCH=${QL_BRANCH}
|
||||||
|
|
||||||
|
RUN set -x \
|
||||||
|
&& apk update -f \
|
||||||
|
&& apk upgrade \
|
||||||
|
&& apk --no-cache add -f bash \
|
||||||
|
coreutils \
|
||||||
|
git \
|
||||||
|
curl \
|
||||||
|
wget \
|
||||||
|
tzdata \
|
||||||
|
perl \
|
||||||
|
openssl \
|
||||||
|
nginx \
|
||||||
|
nodejs \
|
||||||
|
jq \
|
||||||
|
openssh \
|
||||||
|
procps \
|
||||||
|
netcat-openbsd \
|
||||||
|
unzip \
|
||||||
|
npm \
|
||||||
|
&& rm -rf /var/cache/apk/* \
|
||||||
|
&& apk update \
|
||||||
|
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
|
||||||
|
&& echo "Asia/Shanghai" > /etc/timezone \
|
||||||
|
&& git config --global user.email "qinglong@@users.noreply.github.com" \
|
||||||
|
&& git config --global user.name "qinglong" \
|
||||||
|
&& git config --global http.postBuffer 524288000 \
|
||||||
|
&& npm install -g pnpm@8.3.1 pm2 tsx \
|
||||||
|
&& rm -rf /root/.pnpm-store \
|
||||||
|
&& rm -rf /root/.local/share/pnpm/store \
|
||||||
|
&& rm -rf /root/.cache \
|
||||||
|
&& rm -rf /root/.npm \
|
||||||
|
&& ulimit -c 0
|
||||||
|
|
||||||
|
ARG SOURCE_COMMIT
|
||||||
|
RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
|
||||||
|
&& cd ${QL_DIR} \
|
||||||
|
&& cp -f .env.example .env \
|
||||||
|
&& chmod 777 ${QL_DIR}/shell/*.sh \
|
||||||
|
&& chmod 777 ${QL_DIR}/docker/*.sh \
|
||||||
|
&& git clone --depth=1 -b ${QL_BRANCH} https://github.com/${QL_MAINTAINER}/qinglong-static.git /static \
|
||||||
|
&& mkdir -p ${QL_DIR}/static \
|
||||||
|
&& cp -rf /static/* ${QL_DIR}/static \
|
||||||
|
&& rm -rf /static
|
||||||
|
|
||||||
|
COPY --from=builder /tmp/build/node_modules/. /ql/node_modules/
|
||||||
|
|
||||||
|
WORKDIR ${QL_DIR}
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=5s --timeout=2s --retries=20 \
|
||||||
|
CMD curl -sf --noproxy '*' http://127.0.0.1:5400/api/health || exit 1
|
||||||
|
|
||||||
|
ENTRYPOINT ["./docker/docker-entrypoint.sh"]
|
||||||
+6
-1
@@ -23,6 +23,10 @@ ENV PNPM_HOME=/root/.local/share/pnpm \
|
|||||||
QL_DIR=/ql \
|
QL_DIR=/ql \
|
||||||
QL_BRANCH=${QL_BRANCH}
|
QL_BRANCH=${QL_BRANCH}
|
||||||
|
|
||||||
|
VOLUME /ql/data
|
||||||
|
|
||||||
|
EXPOSE 5700
|
||||||
|
|
||||||
RUN set -x \
|
RUN set -x \
|
||||||
&& apk update -f \
|
&& apk update -f \
|
||||||
&& apk upgrade \
|
&& apk upgrade \
|
||||||
@@ -53,7 +57,8 @@ RUN set -x \
|
|||||||
&& rm -rf /root/.pnpm-store \
|
&& rm -rf /root/.pnpm-store \
|
||||||
&& rm -rf /root/.local/share/pnpm/store \
|
&& rm -rf /root/.local/share/pnpm/store \
|
||||||
&& rm -rf /root/.cache \
|
&& rm -rf /root/.cache \
|
||||||
&& rm -rf /root/.npm
|
&& rm -rf /root/.npm \
|
||||||
|
&& ulimit -c 0
|
||||||
|
|
||||||
ARG SOURCE_COMMIT
|
ARG SOURCE_COMMIT
|
||||||
RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
|
RUN git clone --depth=1 -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
|
||||||
|
|||||||
+1
-1
@@ -89,7 +89,7 @@
|
|||||||
"sequelize": "^6.25.5",
|
"sequelize": "^6.25.5",
|
||||||
"serve-handler": "^6.1.3",
|
"serve-handler": "^6.1.3",
|
||||||
"sockjs": "^0.3.24",
|
"sockjs": "^0.3.24",
|
||||||
"sqlite3": "git+https://github.com/whyour/node-sqlite3.git#v1.0.4",
|
"sqlite3": "git+https://github.com/whyour/node-sqlite3.git#v1.0.3",
|
||||||
"tar": "^6.1.15",
|
"tar": "^6.1.15",
|
||||||
"toad-scheduler": "^1.6.0",
|
"toad-scheduler": "^1.6.0",
|
||||||
"typedi": "^0.10.0",
|
"typedi": "^0.10.0",
|
||||||
|
|||||||
Generated
+98
-147
@@ -102,7 +102,7 @@ dependencies:
|
|||||||
version: 3.3.0
|
version: 3.3.0
|
||||||
sequelize:
|
sequelize:
|
||||||
specifier: ^6.25.5
|
specifier: ^6.25.5
|
||||||
version: 6.32.0(@whyour/sqlite3@1.0.4)
|
version: 6.32.0(@whyour/sqlite3@1.0.3)
|
||||||
serve-handler:
|
serve-handler:
|
||||||
specifier: ^6.1.3
|
specifier: ^6.1.3
|
||||||
version: 6.1.5
|
version: 6.1.5
|
||||||
@@ -110,8 +110,8 @@ dependencies:
|
|||||||
specifier: ^0.3.24
|
specifier: ^0.3.24
|
||||||
version: 0.3.24
|
version: 0.3.24
|
||||||
sqlite3:
|
sqlite3:
|
||||||
specifier: git+https://github.com/whyour/node-sqlite3.git#v1.0.4
|
specifier: git+https://github.com/whyour/node-sqlite3.git#v1.0.3
|
||||||
version: github.com/whyour/node-sqlite3/4fcd31f80caa3fc292356b9d99258b601c620488
|
version: github.com/whyour/node-sqlite3/3a00af0b5d7603b7f1b290032507320b18a6b741
|
||||||
tar:
|
tar:
|
||||||
specifier: ^6.1.15
|
specifier: ^6.1.15
|
||||||
version: 6.1.15
|
version: 6.1.15
|
||||||
@@ -4044,6 +4044,24 @@ packages:
|
|||||||
react-is: 16.13.1
|
react-is: 16.13.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@mapbox/node-pre-gyp@1.0.11:
|
||||||
|
resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
detect-libc: 2.0.1
|
||||||
|
https-proxy-agent: 5.0.1
|
||||||
|
make-dir: 3.1.0
|
||||||
|
node-fetch: 2.7.0
|
||||||
|
nopt: 5.0.0
|
||||||
|
npmlog: 5.0.1
|
||||||
|
rimraf: 3.0.2
|
||||||
|
semver: 7.5.4
|
||||||
|
tar: 6.1.15
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- encoding
|
||||||
|
- supports-color
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@monaco-editor/loader@1.3.3(monaco-editor@0.33.0):
|
/@monaco-editor/loader@1.3.3(monaco-editor@0.33.0):
|
||||||
resolution: {integrity: sha512-6KKF4CTzcJiS8BJwtxtfyYt9shBiEv32ateQ9T4UVogwn4HM/uPo9iJd2Dmbkpz8CM6Y0PDUpjnZzCwC+eYo2Q==}
|
resolution: {integrity: sha512-6KKF4CTzcJiS8BJwtxtfyYt9shBiEv32ateQ9T4UVogwn4HM/uPo9iJd2Dmbkpz8CM6Y0PDUpjnZzCwC+eYo2Q==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -6440,7 +6458,14 @@ packages:
|
|||||||
resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
|
resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
|
||||||
|
/are-we-there-yet@2.0.0:
|
||||||
|
resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
dependencies:
|
||||||
|
delegates: 1.0.0
|
||||||
|
readable-stream: 3.6.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/are-we-there-yet@3.0.1:
|
/are-we-there-yet@3.0.1:
|
||||||
resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==}
|
resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==}
|
||||||
@@ -6805,6 +6830,7 @@ packages:
|
|||||||
|
|
||||||
/base64-js@1.5.1:
|
/base64-js@1.5.1:
|
||||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/before@0.0.1:
|
/before@0.0.1:
|
||||||
resolution: {integrity: sha512-1J5SWbkoVJH9DTALN8igB4p+nPKZzPrJ/HomqBDLpfUvDXCdjdBmBUcH5McZfur0lftVssVU6BZug5NYh87zTw==}
|
resolution: {integrity: sha512-1J5SWbkoVJH9DTALN8igB4p+nPKZzPrJ/HomqBDLpfUvDXCdjdBmBUcH5McZfur0lftVssVU6BZug5NYh87zTw==}
|
||||||
@@ -6829,20 +6855,6 @@ packages:
|
|||||||
underscore: 1.4.4
|
underscore: 1.4.4
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/bindings@1.5.0:
|
|
||||||
resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
|
|
||||||
dependencies:
|
|
||||||
file-uri-to-path: 1.0.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/bl@4.1.0:
|
|
||||||
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
|
|
||||||
dependencies:
|
|
||||||
buffer: 5.7.1
|
|
||||||
inherits: 2.0.4
|
|
||||||
readable-stream: 3.6.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/block-stream2@2.1.0:
|
/block-stream2@2.1.0:
|
||||||
resolution: {integrity: sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==}
|
resolution: {integrity: sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -7015,13 +7027,6 @@ packages:
|
|||||||
isarray: 1.0.0
|
isarray: 1.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/buffer@5.7.1:
|
|
||||||
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
|
|
||||||
dependencies:
|
|
||||||
base64-js: 1.5.1
|
|
||||||
ieee754: 1.2.1
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/builtin-status-codes@3.0.0:
|
/builtin-status-codes@3.0.0:
|
||||||
resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==}
|
resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -7189,10 +7194,6 @@ packages:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.2
|
fsevents: 2.3.2
|
||||||
|
|
||||||
/chownr@1.1.4:
|
|
||||||
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/chownr@2.0.0:
|
/chownr@2.0.0:
|
||||||
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
|
resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -7346,7 +7347,6 @@ packages:
|
|||||||
hasBin: true
|
hasBin: true
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
|
||||||
|
|
||||||
/color@3.2.1:
|
/color@3.2.1:
|
||||||
resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==}
|
resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==}
|
||||||
@@ -7463,7 +7463,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
|
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
|
||||||
|
|
||||||
/constants-browserify@1.0.0:
|
/constants-browserify@1.0.0:
|
||||||
resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==}
|
resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==}
|
||||||
@@ -7901,11 +7900,6 @@ packages:
|
|||||||
mimic-response: 3.1.0
|
mimic-response: 3.1.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/deep-extend@0.6.0:
|
|
||||||
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
|
|
||||||
engines: {node: '>=4.0.0'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/deep-is@0.1.4:
|
/deep-is@0.1.4:
|
||||||
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -7981,7 +7975,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==}
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
|
||||||
|
|
||||||
/depd@2.0.0:
|
/depd@2.0.0:
|
||||||
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
|
||||||
@@ -8770,11 +8763,6 @@ packages:
|
|||||||
clone-regexp: 2.2.0
|
clone-regexp: 2.2.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/expand-template@2.0.3:
|
|
||||||
resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/express-jwt@6.1.2:
|
/express-jwt@6.1.2:
|
||||||
resolution: {integrity: sha512-l5dlf5lNM/1EODMsJGfHn1VnrhhsUYEetzrKFStJZLjFQXtR+HGdBiW+jUNZ+ISsFe+h7Wl/hQKjLrY2TX0Qkg==}
|
resolution: {integrity: sha512-l5dlf5lNM/1EODMsJGfHn1VnrhhsUYEetzrKFStJZLjFQXtR+HGdBiW+jUNZ+ISsFe+h7Wl/hQKjLrY2TX0Qkg==}
|
||||||
engines: {node: '>= 8.0.0'}
|
engines: {node: '>= 8.0.0'}
|
||||||
@@ -8949,10 +8937,6 @@ packages:
|
|||||||
moment: 2.29.4
|
moment: 2.29.4
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/file-uri-to-path@1.0.0:
|
|
||||||
resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/file-uri-to-path@2.0.0:
|
/file-uri-to-path@2.0.0:
|
||||||
resolution: {integrity: sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==}
|
resolution: {integrity: sha512-hjPFI8oE/2iQPVe4gbrJ73Pp+Xfub2+WI2LlXDbsaJBwT5wuMh35WNWVYYTpnz895shtwfyutMFLFywpQAFdLg==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
@@ -9114,10 +9098,6 @@ packages:
|
|||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/fs-constants@1.0.0:
|
|
||||||
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/fs-extra@10.1.0:
|
/fs-extra@10.1.0:
|
||||||
resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
|
resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
@@ -9187,6 +9167,21 @@ packages:
|
|||||||
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
|
resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/gauge@3.0.2:
|
||||||
|
resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
dependencies:
|
||||||
|
aproba: 2.0.0
|
||||||
|
color-support: 1.1.3
|
||||||
|
console-control-strings: 1.1.0
|
||||||
|
has-unicode: 2.0.1
|
||||||
|
object-assign: 4.1.1
|
||||||
|
signal-exit: 3.0.7
|
||||||
|
string-width: 4.2.3
|
||||||
|
strip-ansi: 6.0.1
|
||||||
|
wide-align: 1.1.5
|
||||||
|
dev: false
|
||||||
|
|
||||||
/gauge@4.0.4:
|
/gauge@4.0.4:
|
||||||
resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==}
|
resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==}
|
||||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||||
@@ -9279,10 +9274,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==}
|
resolution: {integrity: sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/github-from-package@0.0.0:
|
|
||||||
resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/glob-parent@5.1.2:
|
/glob-parent@5.1.2:
|
||||||
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
@@ -9461,7 +9452,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
|
resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
|
||||||
|
|
||||||
/has@1.0.3:
|
/has@1.0.3:
|
||||||
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
|
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
|
||||||
@@ -9718,6 +9708,7 @@ packages:
|
|||||||
|
|
||||||
/ieee754@1.2.1:
|
/ieee754@1.2.1:
|
||||||
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/ignore-by-default@1.0.1:
|
/ignore-by-default@1.0.1:
|
||||||
resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==}
|
resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==}
|
||||||
@@ -9802,6 +9793,7 @@ packages:
|
|||||||
|
|
||||||
/ini@1.3.8:
|
/ini@1.3.8:
|
||||||
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
|
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/internal-slot@1.0.5:
|
/internal-slot@1.0.5:
|
||||||
resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==}
|
resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==}
|
||||||
@@ -10816,6 +10808,13 @@ packages:
|
|||||||
semver: 5.7.1
|
semver: 5.7.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/make-dir@3.1.0:
|
||||||
|
resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
dependencies:
|
||||||
|
semver: 6.3.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/make-error@1.3.6:
|
/make-error@1.3.6:
|
||||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -11109,10 +11108,6 @@ packages:
|
|||||||
yallist: 4.0.0
|
yallist: 4.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/mkdirp-classic@0.5.3:
|
|
||||||
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/mkdirp@0.5.6:
|
/mkdirp@0.5.6:
|
||||||
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
|
resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -11178,10 +11173,6 @@ packages:
|
|||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/napi-build-utils@1.0.2:
|
|
||||||
resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/natural-compare-lite@1.4.0:
|
/natural-compare-lite@1.4.0:
|
||||||
resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
|
resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -11239,13 +11230,6 @@ packages:
|
|||||||
tslib: 2.5.3
|
tslib: 2.5.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/node-abi@3.52.0:
|
|
||||||
resolution: {integrity: sha512-JJ98b02z16ILv7859irtXn4oUaFWADtvkzy2c0IAatNVX2Mc9Yoh8z6hZInn3QwvMEYhHuQloYi+TTQy67SIdQ==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
dependencies:
|
|
||||||
semver: 7.5.4
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/node-abort-controller@3.1.1:
|
/node-abort-controller@3.1.1:
|
||||||
resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==}
|
resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -11259,6 +11243,18 @@ packages:
|
|||||||
engines: {node: '>=10.5.0'}
|
engines: {node: '>=10.5.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/node-fetch@2.7.0:
|
||||||
|
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
||||||
|
engines: {node: 4.x || >=6.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
encoding: ^0.1.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
encoding:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
whatwg-url: 5.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/node-fetch@3.3.1:
|
/node-fetch@3.3.1:
|
||||||
resolution: {integrity: sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==}
|
resolution: {integrity: sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==}
|
||||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
@@ -11372,7 +11368,6 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
abbrev: 1.1.1
|
abbrev: 1.1.1
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
|
||||||
|
|
||||||
/normalize-package-data@2.5.0:
|
/normalize-package-data@2.5.0:
|
||||||
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
|
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
|
||||||
@@ -11441,6 +11436,15 @@ packages:
|
|||||||
path-key: 4.0.0
|
path-key: 4.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/npmlog@5.0.1:
|
||||||
|
resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==}
|
||||||
|
dependencies:
|
||||||
|
are-we-there-yet: 2.0.0
|
||||||
|
console-control-strings: 1.1.0
|
||||||
|
gauge: 3.0.2
|
||||||
|
set-blocking: 2.0.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/npmlog@6.0.2:
|
/npmlog@6.0.2:
|
||||||
resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==}
|
resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==}
|
||||||
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
|
||||||
@@ -12483,25 +12487,6 @@ packages:
|
|||||||
source-map-js: 1.0.2
|
source-map-js: 1.0.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/prebuild-install@7.1.1:
|
|
||||||
resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
hasBin: true
|
|
||||||
dependencies:
|
|
||||||
detect-libc: 2.0.1
|
|
||||||
expand-template: 2.0.3
|
|
||||||
github-from-package: 0.0.0
|
|
||||||
minimist: 1.2.8
|
|
||||||
mkdirp-classic: 0.5.3
|
|
||||||
napi-build-utils: 1.0.2
|
|
||||||
node-abi: 3.52.0
|
|
||||||
pump: 3.0.0
|
|
||||||
rc: 1.2.8
|
|
||||||
simple-get: 4.0.1
|
|
||||||
tar-fs: 2.1.1
|
|
||||||
tunnel-agent: 0.6.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/prelude-ls@1.1.2:
|
/prelude-ls@1.1.2:
|
||||||
resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==}
|
resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
@@ -13651,16 +13636,6 @@ packages:
|
|||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/rc@1.2.8:
|
|
||||||
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
|
|
||||||
hasBin: true
|
|
||||||
dependencies:
|
|
||||||
deep-extend: 0.6.0
|
|
||||||
ini: 1.3.8
|
|
||||||
minimist: 1.2.8
|
|
||||||
strip-json-comments: 2.0.1
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/react-copy-to-clipboard@5.1.0(react@18.2.0):
|
/react-copy-to-clipboard@5.1.0(react@18.2.0):
|
||||||
resolution: {integrity: sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==}
|
resolution: {integrity: sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -14460,7 +14435,6 @@ packages:
|
|||||||
/semver@6.3.1:
|
/semver@6.3.1:
|
||||||
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dev: true
|
|
||||||
|
|
||||||
/semver@7.5.1:
|
/semver@7.5.1:
|
||||||
resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==}
|
resolution: {integrity: sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==}
|
||||||
@@ -14503,7 +14477,7 @@ packages:
|
|||||||
engines: {node: '>= 10.0.0'}
|
engines: {node: '>= 10.0.0'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/sequelize@6.32.0(@whyour/sqlite3@1.0.4):
|
/sequelize@6.32.0(@whyour/sqlite3@1.0.3):
|
||||||
resolution: {integrity: sha512-gMd1M6kPANyrCeU/vtgEP5gnse7sVsiKbJyz7p4huuW8zZcRopj47UlglvdrMuIoqksZmsUPfApmMo6ZlJpcvg==}
|
resolution: {integrity: sha512-gMd1M6kPANyrCeU/vtgEP5gnse7sVsiKbJyz7p4huuW8zZcRopj47UlglvdrMuIoqksZmsUPfApmMo6ZlJpcvg==}
|
||||||
engines: {node: '>=10.0.0'}
|
engines: {node: '>=10.0.0'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -14548,7 +14522,7 @@ packages:
|
|||||||
retry-as-promised: 7.0.4
|
retry-as-promised: 7.0.4
|
||||||
semver: 7.5.1
|
semver: 7.5.1
|
||||||
sequelize-pool: 7.1.0
|
sequelize-pool: 7.1.0
|
||||||
sqlite3: github.com/whyour/node-sqlite3/4fcd31f80caa3fc292356b9d99258b601c620488
|
sqlite3: github.com/whyour/node-sqlite3/3a00af0b5d7603b7f1b290032507320b18a6b741
|
||||||
toposort-class: 1.0.1
|
toposort-class: 1.0.1
|
||||||
uuid: 8.3.2
|
uuid: 8.3.2
|
||||||
validator: 13.9.0
|
validator: 13.9.0
|
||||||
@@ -14592,7 +14566,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
|
||||||
|
|
||||||
/setimmediate@1.0.5:
|
/setimmediate@1.0.5:
|
||||||
resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
|
resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==}
|
||||||
@@ -14653,18 +14626,6 @@ packages:
|
|||||||
/signal-exit@3.0.7:
|
/signal-exit@3.0.7:
|
||||||
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
|
||||||
|
|
||||||
/simple-concat@1.0.1:
|
|
||||||
resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/simple-get@4.0.1:
|
|
||||||
resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
|
|
||||||
dependencies:
|
|
||||||
decompress-response: 6.0.0
|
|
||||||
once: 1.4.0
|
|
||||||
simple-concat: 1.0.1
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/simple-swizzle@0.2.2:
|
/simple-swizzle@0.2.2:
|
||||||
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
|
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -15094,11 +15055,6 @@ packages:
|
|||||||
min-indent: 1.0.1
|
min-indent: 1.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/strip-json-comments@2.0.1:
|
|
||||||
resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/strip-json-comments@3.1.1:
|
/strip-json-comments@3.1.1:
|
||||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -15351,26 +15307,6 @@ packages:
|
|||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/tar-fs@2.1.1:
|
|
||||||
resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==}
|
|
||||||
dependencies:
|
|
||||||
chownr: 1.1.4
|
|
||||||
mkdirp-classic: 0.5.3
|
|
||||||
pump: 3.0.0
|
|
||||||
tar-stream: 2.2.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/tar-stream@2.2.0:
|
|
||||||
resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
|
|
||||||
engines: {node: '>=6'}
|
|
||||||
dependencies:
|
|
||||||
bl: 4.1.0
|
|
||||||
end-of-stream: 1.4.4
|
|
||||||
fs-constants: 1.0.0
|
|
||||||
inherits: 2.0.4
|
|
||||||
readable-stream: 3.6.2
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/tar@6.1.15:
|
/tar@6.1.15:
|
||||||
resolution: {integrity: sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==}
|
resolution: {integrity: sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
@@ -15539,6 +15475,10 @@ packages:
|
|||||||
universalify: 0.1.2
|
universalify: 0.1.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/tr46@0.0.3:
|
||||||
|
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/tree-kill@1.2.2:
|
/tree-kill@1.2.2:
|
||||||
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
|
resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -15650,6 +15590,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
|
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
|
||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer: 5.2.1
|
safe-buffer: 5.2.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/tween-functions@1.2.0:
|
/tween-functions@1.2.0:
|
||||||
resolution: {integrity: sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==}
|
resolution: {integrity: sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==}
|
||||||
@@ -16175,6 +16116,10 @@ packages:
|
|||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/webidl-conversions@3.0.1:
|
||||||
|
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/webpack-sources@3.2.3:
|
/webpack-sources@3.2.3:
|
||||||
resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
|
resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==}
|
||||||
engines: {node: '>=10.13.0'}
|
engines: {node: '>=10.13.0'}
|
||||||
@@ -16232,6 +16177,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==}
|
resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==}
|
||||||
engines: {node: '>=0.8.0'}
|
engines: {node: '>=0.8.0'}
|
||||||
|
|
||||||
|
/whatwg-url@5.0.0:
|
||||||
|
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
||||||
|
dependencies:
|
||||||
|
tr46: 0.0.3
|
||||||
|
webidl-conversions: 3.0.1
|
||||||
|
dev: false
|
||||||
|
|
||||||
/which-boxed-primitive@1.0.2:
|
/which-boxed-primitive@1.0.2:
|
||||||
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -16301,7 +16253,6 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
string-width: 4.2.3
|
string-width: 4.2.3
|
||||||
dev: false
|
dev: false
|
||||||
optional: true
|
|
||||||
|
|
||||||
/win-release@1.1.1:
|
/win-release@1.1.1:
|
||||||
resolution: {integrity: sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw==}
|
resolution: {integrity: sha512-iCRnKVvGxOQdsKhcQId2PXV1vV3J/sDPXKA4Oe9+Eti2nb2ESEsYHRYls/UjoUW3bIc5ZDO8dTH50A/5iVN+bw==}
|
||||||
@@ -16464,23 +16415,23 @@ packages:
|
|||||||
strip-indent: 2.0.0
|
strip-indent: 2.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
github.com/whyour/node-sqlite3/4fcd31f80caa3fc292356b9d99258b601c620488:
|
github.com/whyour/node-sqlite3/3a00af0b5d7603b7f1b290032507320b18a6b741:
|
||||||
resolution: {tarball: https://codeload.github.com/whyour/node-sqlite3/tar.gz/4fcd31f80caa3fc292356b9d99258b601c620488}
|
resolution: {tarball: https://codeload.github.com/whyour/node-sqlite3/tar.gz/3a00af0b5d7603b7f1b290032507320b18a6b741}
|
||||||
name: '@whyour/sqlite3'
|
name: '@whyour/sqlite3'
|
||||||
version: 1.0.4
|
version: 1.0.3
|
||||||
requiresBuild: true
|
requiresBuild: true
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
node-gyp:
|
node-gyp:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
bindings: 1.5.0
|
'@mapbox/node-pre-gyp': 1.0.11
|
||||||
node-addon-api: 4.3.0
|
node-addon-api: 4.3.0
|
||||||
prebuild-install: 7.1.1
|
|
||||||
tar: 6.1.15
|
tar: 6.1.15
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
node-gyp: 8.4.1
|
node-gyp: 8.4.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- bluebird
|
- bluebird
|
||||||
|
- encoding
|
||||||
- supports-color
|
- supports-color
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
|||||||
+38
-23
@@ -816,7 +816,18 @@ function ChangeUserId(desp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function qywxamNotify(text, desp) {
|
async function qywxamNotify(text, desp) {
|
||||||
|
const MAX_LENGTH = 900;
|
||||||
|
if (desp.length > MAX_LENGTH) {
|
||||||
|
let d = desp.substr(0, MAX_LENGTH) + "\n==More==";
|
||||||
|
await do_qywxamNotify(text, d);
|
||||||
|
await qywxamNotify(text, desp.substr(MAX_LENGTH));
|
||||||
|
} else {
|
||||||
|
return await do_qywxamNotify(text,desp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function do_qywxamNotify(text, desp) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
if (QYWX_AM) {
|
if (QYWX_AM) {
|
||||||
const QYWX_AM_AY = QYWX_AM.split(',');
|
const QYWX_AM_AY = QYWX_AM.split(',');
|
||||||
@@ -1315,6 +1326,31 @@ function webhookNotify(text, desp) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseString(input) {
|
||||||
|
const regex = /(\w+):\s*((?:(?!\n\w+:).)*)/g;
|
||||||
|
const matches = {};
|
||||||
|
|
||||||
|
let match;
|
||||||
|
while ((match = regex.exec(input)) !== null) {
|
||||||
|
const [, key, value] = match;
|
||||||
|
const _key = key.trim();
|
||||||
|
if (!_key || matches[_key]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _value = value.trim();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const jsonValue = JSON.parse(_value);
|
||||||
|
matches[_key] = jsonValue;
|
||||||
|
} catch (error) {
|
||||||
|
matches[_key] = _value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
function parseHeaders(headers) {
|
function parseHeaders(headers) {
|
||||||
if (!headers) return {};
|
if (!headers) return {};
|
||||||
|
|
||||||
@@ -1344,28 +1380,7 @@ function parseBody(body, contentType) {
|
|||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsed = {};
|
const parsed = parseString(body);
|
||||||
let key;
|
|
||||||
let val;
|
|
||||||
let i;
|
|
||||||
|
|
||||||
body &&
|
|
||||||
body.split('\n').forEach(function parser(line) {
|
|
||||||
i = line.indexOf(':');
|
|
||||||
key = line.substring(0, i).trim();
|
|
||||||
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) {
|
switch (contentType) {
|
||||||
case 'multipart/form-data':
|
case 'multipart/form-data':
|
||||||
|
|||||||
+75
-77
@@ -578,7 +578,9 @@ def aibotk(title: str, content: str) -> None:
|
|||||||
or not push_config.get("AIBOTK_TYPE")
|
or not push_config.get("AIBOTK_TYPE")
|
||||||
or not push_config.get("AIBOTK_NAME")
|
or not push_config.get("AIBOTK_NAME")
|
||||||
):
|
):
|
||||||
print("智能微秘书 的 AIBOTK_KEY 或者 AIBOTK_TYPE 或者 AIBOTK_NAME 未设置!!\n取消推送")
|
print(
|
||||||
|
"智能微秘书 的 AIBOTK_KEY 或者 AIBOTK_TYPE 或者 AIBOTK_NAME 未设置!!\n取消推送"
|
||||||
|
)
|
||||||
return
|
return
|
||||||
print("智能微秘书 服务启动")
|
print("智能微秘书 服务启动")
|
||||||
|
|
||||||
@@ -748,29 +750,25 @@ def parse_headers(headers):
|
|||||||
return parsed
|
return parsed
|
||||||
|
|
||||||
|
|
||||||
|
def parse_string(input_string):
|
||||||
|
matches = {}
|
||||||
|
pattern = r'(\w+):\s*((?:(?!\n\w+:).)*)'
|
||||||
|
regex = re.compile(pattern)
|
||||||
|
for match in regex.finditer(input_string):
|
||||||
|
key, value = match.group(1).strip(), match.group(2).strip()
|
||||||
|
try:
|
||||||
|
json_value = json.loads(value)
|
||||||
|
matches[key] = json_value
|
||||||
|
except:
|
||||||
|
matches[key] = value
|
||||||
|
return matches
|
||||||
|
|
||||||
|
|
||||||
def parse_body(body, content_type):
|
def parse_body(body, content_type):
|
||||||
if not body or content_type == "text/plain":
|
if not body or content_type == "text/plain":
|
||||||
return body
|
return body
|
||||||
|
|
||||||
parsed = {}
|
parsed = parse_string(input_string)
|
||||||
lines = body.split("\n")
|
|
||||||
|
|
||||||
for line in lines:
|
|
||||||
i = line.find(":")
|
|
||||||
if i == -1:
|
|
||||||
continue
|
|
||||||
|
|
||||||
key = line[:i].strip()
|
|
||||||
val = line[i + 1 :].strip()
|
|
||||||
|
|
||||||
if not key or key in parsed:
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
json_value = json.loads(val)
|
|
||||||
parsed[key] = json_value
|
|
||||||
except:
|
|
||||||
parsed[key] = val
|
|
||||||
|
|
||||||
if content_type == "application/x-www-form-urlencoded":
|
if content_type == "application/x-www-form-urlencoded":
|
||||||
data = urlencode(parsed, doseq=True)
|
data = urlencode(parsed, doseq=True)
|
||||||
@@ -841,60 +839,61 @@ def one() -> str:
|
|||||||
return res["hitokoto"] + " ----" + res["from"]
|
return res["hitokoto"] + " ----" + res["from"]
|
||||||
|
|
||||||
|
|
||||||
if push_config.get("BARK_PUSH"):
|
def add_notify_function():
|
||||||
notify_function.append(bark)
|
if push_config.get("BARK_PUSH"):
|
||||||
if push_config.get("CONSOLE"):
|
notify_function.append(bark)
|
||||||
notify_function.append(console)
|
if push_config.get("CONSOLE"):
|
||||||
if push_config.get("DD_BOT_TOKEN") and push_config.get("DD_BOT_SECRET"):
|
notify_function.append(console)
|
||||||
notify_function.append(dingding_bot)
|
if push_config.get("DD_BOT_TOKEN") and push_config.get("DD_BOT_SECRET"):
|
||||||
if push_config.get("FSKEY"):
|
notify_function.append(dingding_bot)
|
||||||
notify_function.append(feishu_bot)
|
if push_config.get("FSKEY"):
|
||||||
if push_config.get("GOBOT_URL") and push_config.get("GOBOT_QQ"):
|
notify_function.append(feishu_bot)
|
||||||
notify_function.append(go_cqhttp)
|
if push_config.get("GOBOT_URL") and push_config.get("GOBOT_QQ"):
|
||||||
if push_config.get("GOTIFY_URL") and push_config.get("GOTIFY_TOKEN"):
|
notify_function.append(go_cqhttp)
|
||||||
notify_function.append(gotify)
|
if push_config.get("GOTIFY_URL") and push_config.get("GOTIFY_TOKEN"):
|
||||||
if push_config.get("IGOT_PUSH_KEY"):
|
notify_function.append(gotify)
|
||||||
notify_function.append(iGot)
|
if push_config.get("IGOT_PUSH_KEY"):
|
||||||
if push_config.get("PUSH_KEY"):
|
notify_function.append(iGot)
|
||||||
notify_function.append(serverJ)
|
if push_config.get("PUSH_KEY"):
|
||||||
if push_config.get("DEER_KEY"):
|
notify_function.append(serverJ)
|
||||||
notify_function.append(pushdeer)
|
if push_config.get("DEER_KEY"):
|
||||||
if push_config.get("CHAT_URL") and push_config.get("CHAT_TOKEN"):
|
notify_function.append(pushdeer)
|
||||||
notify_function.append(chat)
|
if push_config.get("CHAT_URL") and push_config.get("CHAT_TOKEN"):
|
||||||
if push_config.get("PUSH_PLUS_TOKEN"):
|
notify_function.append(chat)
|
||||||
notify_function.append(pushplus_bot)
|
if push_config.get("PUSH_PLUS_TOKEN"):
|
||||||
if push_config.get("QMSG_KEY") and push_config.get("QMSG_TYPE"):
|
notify_function.append(pushplus_bot)
|
||||||
notify_function.append(qmsg_bot)
|
if push_config.get("QMSG_KEY") and push_config.get("QMSG_TYPE"):
|
||||||
if push_config.get("QYWX_AM"):
|
notify_function.append(qmsg_bot)
|
||||||
notify_function.append(wecom_app)
|
if push_config.get("QYWX_AM"):
|
||||||
if push_config.get("QYWX_KEY"):
|
notify_function.append(wecom_app)
|
||||||
notify_function.append(wecom_bot)
|
if push_config.get("QYWX_KEY"):
|
||||||
if push_config.get("TG_BOT_TOKEN") and push_config.get("TG_USER_ID"):
|
notify_function.append(wecom_bot)
|
||||||
notify_function.append(telegram_bot)
|
if push_config.get("TG_BOT_TOKEN") and push_config.get("TG_USER_ID"):
|
||||||
if (
|
notify_function.append(telegram_bot)
|
||||||
push_config.get("AIBOTK_KEY")
|
if (
|
||||||
and push_config.get("AIBOTK_TYPE")
|
push_config.get("AIBOTK_KEY")
|
||||||
and push_config.get("AIBOTK_NAME")
|
and push_config.get("AIBOTK_TYPE")
|
||||||
):
|
and push_config.get("AIBOTK_NAME")
|
||||||
notify_function.append(aibotk)
|
):
|
||||||
if (
|
notify_function.append(aibotk)
|
||||||
push_config.get("SMTP_SERVER")
|
if (
|
||||||
and push_config.get("SMTP_SSL")
|
push_config.get("SMTP_SERVER")
|
||||||
and push_config.get("SMTP_EMAIL")
|
and push_config.get("SMTP_SSL")
|
||||||
and push_config.get("SMTP_PASSWORD")
|
and push_config.get("SMTP_EMAIL")
|
||||||
and push_config.get("SMTP_NAME")
|
and push_config.get("SMTP_PASSWORD")
|
||||||
):
|
and push_config.get("SMTP_NAME")
|
||||||
notify_function.append(smtp)
|
):
|
||||||
if push_config.get("PUSHME_KEY"):
|
notify_function.append(smtp)
|
||||||
notify_function.append(pushme)
|
if push_config.get("PUSHME_KEY"):
|
||||||
if (
|
notify_function.append(pushme)
|
||||||
push_config.get("CHRONOCAT_URL")
|
if (
|
||||||
and push_config.get("CHRONOCAT_QQ")
|
push_config.get("CHRONOCAT_URL")
|
||||||
and push_config.get("CHRONOCAT_TOKEN")
|
and push_config.get("CHRONOCAT_QQ")
|
||||||
):
|
and push_config.get("CHRONOCAT_TOKEN")
|
||||||
notify_function.append(chronocat)
|
):
|
||||||
if push_config.get("WEBHOOK_URL") and push_config.get("WEBHOOK_METHOD"):
|
notify_function.append(chronocat)
|
||||||
notify_function.append(custom_notify)
|
if push_config.get("WEBHOOK_URL") and push_config.get("WEBHOOK_METHOD"):
|
||||||
|
notify_function.append(custom_notify)
|
||||||
|
|
||||||
|
|
||||||
def send(title: str, content: str) -> None:
|
def send(title: str, content: str) -> None:
|
||||||
@@ -910,10 +909,9 @@ def send(title: str, content: str) -> None:
|
|||||||
return
|
return
|
||||||
|
|
||||||
hitokoto = push_config.get("HITOKOTO")
|
hitokoto = push_config.get("HITOKOTO")
|
||||||
|
content += "\n\n" + one() if hitokoto else ""
|
||||||
|
|
||||||
text = one() if hitokoto else ""
|
add_notify_function()
|
||||||
content += "\n\n" + text
|
|
||||||
|
|
||||||
ts = [
|
ts = [
|
||||||
threading.Thread(target=mode, args=(title, content), name=mode.__name__)
|
threading.Thread(target=mode, args=(title, content), name=mode.__name__)
|
||||||
for mode in notify_function
|
for mode in notify_function
|
||||||
|
|||||||
+2
-2
@@ -267,8 +267,8 @@ update_qinglong() {
|
|||||||
echo -e "使用 ${mirror} 源更新...\n"
|
echo -e "使用 ${mirror} 源更新...\n"
|
||||||
|
|
||||||
local primary_branch="master"
|
local primary_branch="master"
|
||||||
if [[ "${QL_BRANCH}" == "develop" ]]; then
|
if [[ "${QL_BRANCH}" == "develop" ]] || [[ "${QL_BRANCH}" == "debian" ]] || [[ "${QL_BRANCH}" == "debian-dev" ]]; then
|
||||||
primary_branch="develop"
|
primary_branch="${QL_BRANCH}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
wget -cqO "${dir_tmp}/ql.zip" "${downloadQLUrl}/${primary_branch}.zip"
|
wget -cqO "${dir_tmp}/ql.zip" "${downloadQLUrl}/${primary_branch}.zip"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { createFromIconfontCN } from '@ant-design/icons';
|
import { createFromIconfontCN } from '@ant-design/icons';
|
||||||
|
|
||||||
const IconFont = createFromIconfontCN({
|
const IconFont = createFromIconfontCN({
|
||||||
scriptUrl: ['//at.alicdn.com/t/c/font_3354854_ob5y15ewlyq.js'],
|
scriptUrl: ['//at.alicdn.com/t/c/font_3354854_lc939gab1iq.js'],
|
||||||
});
|
});
|
||||||
|
|
||||||
export default IconFont;
|
export default IconFont;
|
||||||
|
|||||||
@@ -100,12 +100,14 @@
|
|||||||
"删除中": "Deleting",
|
"删除中": "Deleting",
|
||||||
"已删除": "Deleted",
|
"已删除": "Deleted",
|
||||||
"删除失败": "Deletion Failed",
|
"删除失败": "Deletion Failed",
|
||||||
|
"已取消": "Cancelled",
|
||||||
"序号": "Number",
|
"序号": "Number",
|
||||||
"备注": "Remarks",
|
"备注": "Remarks",
|
||||||
"更新时间": "Update Time",
|
"更新时间": "Update Time",
|
||||||
"创建时间": "Creation Time",
|
"创建时间": "Creation Time",
|
||||||
"确认删除依赖": "Confirm to delete the dependency",
|
"确认删除依赖": "Confirm to delete the dependency",
|
||||||
"确认重新安装": "Confirm to reinstall",
|
"确认重新安装": "Confirm to reinstall",
|
||||||
|
"确认取消安装": "Confirm to cancel install",
|
||||||
"确认删除选中的依赖吗": "Confirm to delete the selected dependencies?",
|
"确认删除选中的依赖吗": "Confirm to delete the selected dependencies?",
|
||||||
"确认重新安装选中的依赖吗": "Confirm to reinstall the selected dependencies?",
|
"确认重新安装选中的依赖吗": "Confirm to reinstall the selected dependencies?",
|
||||||
"请输入名称": "Please enter a name",
|
"请输入名称": "Please enter a name",
|
||||||
@@ -237,6 +239,7 @@
|
|||||||
"系统将在": "The system will restart in",
|
"系统将在": "The system will restart in",
|
||||||
"秒后自动刷新": "seconds and automatically refresh",
|
"秒后自动刷新": "seconds and automatically refresh",
|
||||||
"检查更新": "Check for Updates",
|
"检查更新": "Check for Updates",
|
||||||
|
"重新启动": "Reboot",
|
||||||
"确认删除应用": "Confirm to delete the application",
|
"确认删除应用": "Confirm to delete the application",
|
||||||
"确认重置": "Confirm to reset",
|
"确认重置": "Confirm to reset",
|
||||||
"确认重置应用": "Confirm to reset the application",
|
"确认重置应用": "Confirm to reset the application",
|
||||||
@@ -393,6 +396,7 @@
|
|||||||
"系统": "System",
|
"系统": "System",
|
||||||
"个人": "Personal",
|
"个人": "Personal",
|
||||||
"重新安装": "Reinstall",
|
"重新安装": "Reinstall",
|
||||||
|
"取消安装": "Cancel Install",
|
||||||
"强制删除": "Force Delete",
|
"强制删除": "Force Delete",
|
||||||
"全部任务": "All Tasks",
|
"全部任务": "All Tasks",
|
||||||
"关联订阅": "Associate Subscription",
|
"关联订阅": "Associate Subscription",
|
||||||
@@ -475,6 +479,6 @@
|
|||||||
"代理地址, 支持HTTP(S)/SOCK5": "Proxy Address, supports HTTP(S)/SOCK5",
|
"代理地址, 支持HTTP(S)/SOCK5": "Proxy Address, supports HTTP(S)/SOCK5",
|
||||||
"NPM 镜像源": "NPM Mirror Source",
|
"NPM 镜像源": "NPM Mirror Source",
|
||||||
"PyPI 镜像源": "PyPI Mirror Source",
|
"PyPI 镜像源": "PyPI Mirror Source",
|
||||||
"alpine linux 镜像源, 例如 https://mirrors.aliyun.com": "Alpine Linux Mirror Source, e.g. https://mirrors.aliyun.com",
|
"alpine linux 镜像源": "Alpine Linux Mirror Source",
|
||||||
"如果恢复失败,可进入容器执行": "If recovery fails, you can enter the container and execute"
|
"如果恢复失败,可进入容器执行": "If recovery fails, you can enter the container and execute"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,12 +100,14 @@
|
|||||||
"删除中": "删除中",
|
"删除中": "删除中",
|
||||||
"已删除": "已删除",
|
"已删除": "已删除",
|
||||||
"删除失败": "删除失败",
|
"删除失败": "删除失败",
|
||||||
|
"已取消": "已取消",
|
||||||
"序号": "序号",
|
"序号": "序号",
|
||||||
"备注": "备注",
|
"备注": "备注",
|
||||||
"更新时间": "更新时间",
|
"更新时间": "更新时间",
|
||||||
"创建时间": "创建时间",
|
"创建时间": "创建时间",
|
||||||
"确认删除依赖": "确认删除依赖",
|
"确认删除依赖": "确认删除依赖",
|
||||||
"确认重新安装": "确认重新安装",
|
"确认重新安装": "确认重新安装",
|
||||||
|
"确认取消安装": "确认取消安装",
|
||||||
"确认删除选中的依赖吗": "确认删除选中的依赖吗",
|
"确认删除选中的依赖吗": "确认删除选中的依赖吗",
|
||||||
"确认重新安装选中的依赖吗": "确认重新安装选中的依赖吗",
|
"确认重新安装选中的依赖吗": "确认重新安装选中的依赖吗",
|
||||||
"请输入名称": "请输入名称",
|
"请输入名称": "请输入名称",
|
||||||
@@ -237,6 +239,7 @@
|
|||||||
"系统将在": "系统将在",
|
"系统将在": "系统将在",
|
||||||
"秒后自动刷新": "秒后自动刷新",
|
"秒后自动刷新": "秒后自动刷新",
|
||||||
"检查更新": "检查更新",
|
"检查更新": "检查更新",
|
||||||
|
"重新启动": "重新启动",
|
||||||
"确认删除应用": "确认删除应用",
|
"确认删除应用": "确认删除应用",
|
||||||
"确认重置": "确认重置",
|
"确认重置": "确认重置",
|
||||||
"确认重置应用": "确认重置应用",
|
"确认重置应用": "确认重置应用",
|
||||||
@@ -393,6 +396,7 @@
|
|||||||
"系统": "系统",
|
"系统": "系统",
|
||||||
"个人": "个人",
|
"个人": "个人",
|
||||||
"重新安装": "重新安装",
|
"重新安装": "重新安装",
|
||||||
|
"取消安装": "取消安装",
|
||||||
"强制删除": "强制删除",
|
"强制删除": "强制删除",
|
||||||
"全部任务": "全部任务",
|
"全部任务": "全部任务",
|
||||||
"关联订阅": "关联订阅",
|
"关联订阅": "关联订阅",
|
||||||
@@ -475,6 +479,6 @@
|
|||||||
"代理地址, 支持HTTP(S)/SOCK5": "代理地址, 支持HTTP(S)/SOCK5",
|
"代理地址, 支持HTTP(S)/SOCK5": "代理地址, 支持HTTP(S)/SOCK5",
|
||||||
"NPM 镜像源": "NPM 镜像源",
|
"NPM 镜像源": "NPM 镜像源",
|
||||||
"PyPI 镜像源": "PyPI 镜像源",
|
"PyPI 镜像源": "PyPI 镜像源",
|
||||||
"alpine linux 镜像源, 例如 https://mirrors.aliyun.com": "alpine linux 镜像源, 例如 https://mirrors.aliyun.com",
|
"alpine linux 镜像源": "alpine linux 镜像源",
|
||||||
"如果恢复失败,可进入容器执行": "如果恢复失败,可进入容器执行"
|
"如果恢复失败,可进入容器执行": "如果恢复失败,可进入容器执行"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ const Config = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'meta+s',
|
'mod+s',
|
||||||
(e) => {
|
(e) => {
|
||||||
updateConfig();
|
updateConfig();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -119,21 +119,17 @@ const CronDetailModal = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onClickItem = (item: LogItem) => {
|
const onClickItem = (item: LogItem) => {
|
||||||
const url = `${config.apiPrefix}logs/${item.filename}?path=${
|
const url = `${config.apiPrefix}logs/detail?file=${item.filename}&path=${
|
||||||
item.directory || ''
|
item.directory || ''
|
||||||
}`;
|
}`;
|
||||||
localStorage.setItem('logCron', url);
|
localStorage.setItem('logCron', url);
|
||||||
setLogUrl(url);
|
setLogUrl(url);
|
||||||
request
|
request.get(url).then(({ code, data }) => {
|
||||||
.get(
|
if (code === 200) {
|
||||||
`${config.apiPrefix}logs/${item.filename}?path=${item.directory || ''}`,
|
setLog(data);
|
||||||
)
|
setIsLogModalVisible(true);
|
||||||
.then(({ code, data }) => {
|
}
|
||||||
if (code === 200) {
|
});
|
||||||
setLog(data);
|
|
||||||
setIsLogModalVisible(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onTabChange = (key: string) => {
|
const onTabChange = (key: string) => {
|
||||||
@@ -159,7 +155,7 @@ const CronDetailModal = ({
|
|||||||
const [s, p] = result;
|
const [s, p] = result;
|
||||||
setScriptInfo({ parent: p, filename: s });
|
setScriptInfo({ parent: p, filename: s });
|
||||||
request
|
request
|
||||||
.get(`${config.apiPrefix}scripts/${s}?path=${p || ''}`)
|
.get(`${config.apiPrefix}scripts/detail?file=${s}&path=${p || ''}`)
|
||||||
.then(({ code, data }) => {
|
.then(({ code, data }) => {
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
setValue(data);
|
setValue(data);
|
||||||
|
|||||||
+111
-37
@@ -22,6 +22,7 @@ import {
|
|||||||
FileTextOutlined,
|
FileTextOutlined,
|
||||||
CloseCircleOutlined,
|
CloseCircleOutlined,
|
||||||
ClockCircleOutlined,
|
ClockCircleOutlined,
|
||||||
|
MinusCircleOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import config from '@/utils/config';
|
import config from '@/utils/config';
|
||||||
import { PageContainer } from '@ant-design/pro-layout';
|
import { PageContainer } from '@ant-design/pro-layout';
|
||||||
@@ -36,20 +37,12 @@ import { SharedContext } from '@/layouts';
|
|||||||
import useTableScrollHeight from '@/hooks/useTableScrollHeight';
|
import useTableScrollHeight from '@/hooks/useTableScrollHeight';
|
||||||
import dayjs from 'dayjs';
|
import dayjs from 'dayjs';
|
||||||
import WebSocketManager from '@/utils/websocket';
|
import WebSocketManager from '@/utils/websocket';
|
||||||
|
import { DependenceStatus, Status } from './type';
|
||||||
|
import IconFont from '@/components/iconfont';
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
const { Search } = Input;
|
const { Search } = Input;
|
||||||
|
|
||||||
enum Status {
|
|
||||||
'安装中',
|
|
||||||
'已安装',
|
|
||||||
'安装失败',
|
|
||||||
'删除中',
|
|
||||||
'已删除',
|
|
||||||
'删除失败',
|
|
||||||
'队列中',
|
|
||||||
}
|
|
||||||
|
|
||||||
enum StatusColor {
|
enum StatusColor {
|
||||||
'processing',
|
'processing',
|
||||||
'success',
|
'success',
|
||||||
@@ -85,6 +78,10 @@ const StatusMap: Record<number, { icon: React.ReactNode; color: string }> = {
|
|||||||
icon: <ClockCircleOutlined />,
|
icon: <ClockCircleOutlined />,
|
||||||
color: 'default',
|
color: 'default',
|
||||||
},
|
},
|
||||||
|
7: {
|
||||||
|
icon: <MinusCircleOutlined />,
|
||||||
|
color: 'default',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const Dependence = () => {
|
const Dependence = () => {
|
||||||
@@ -108,6 +105,40 @@ const Dependence = () => {
|
|||||||
key: 'status',
|
key: 'status',
|
||||||
width: 120,
|
width: 120,
|
||||||
dataIndex: 'status',
|
dataIndex: 'status',
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
text: intl.get('队列中'),
|
||||||
|
value: DependenceStatus.queued,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: intl.get('安装中'),
|
||||||
|
value: DependenceStatus.installing,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: intl.get('已安装'),
|
||||||
|
value: DependenceStatus.installed,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: intl.get('安装失败'),
|
||||||
|
value: DependenceStatus.installFailed,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: intl.get('删除中'),
|
||||||
|
value: DependenceStatus.removing,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: intl.get('已删除'),
|
||||||
|
value: DependenceStatus.removed,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: intl.get('删除失败'),
|
||||||
|
value: DependenceStatus.removeFailed,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: intl.get('已取消'),
|
||||||
|
value: DependenceStatus.cancelled,
|
||||||
|
},
|
||||||
|
],
|
||||||
render: (text: string, record: any, index: number) => {
|
render: (text: string, record: any, index: number) => {
|
||||||
return (
|
return (
|
||||||
<Space size="middle" style={{ cursor: 'text' }}>
|
<Space size="middle" style={{ cursor: 'text' }}>
|
||||||
@@ -154,35 +185,46 @@ const Dependence = () => {
|
|||||||
const isPc = !isPhone;
|
const isPc = !isPhone;
|
||||||
return (
|
return (
|
||||||
<Space size="middle">
|
<Space size="middle">
|
||||||
<Tooltip title={isPc ? intl.get('日志') : ''}>
|
{![Status.队列中, Status.已取消].includes(record.status) && (
|
||||||
<a
|
<Tooltip title={isPc ? intl.get('日志') : ''}>
|
||||||
onClick={() => {
|
<a
|
||||||
setLogDependence({ ...record, timestamp: Date.now() });
|
onClick={() => {
|
||||||
}}
|
setLogDependence({ ...record, timestamp: Date.now() });
|
||||||
>
|
}}
|
||||||
<FileTextOutlined />
|
>
|
||||||
</a>
|
<FileTextOutlined />
|
||||||
</Tooltip>
|
</a>
|
||||||
{record.status !== Status.安装中 &&
|
</Tooltip>
|
||||||
record.status !== Status.删除中 && (
|
)}
|
||||||
<>
|
{[Status.队列中, Status.安装中, Status.删除中].includes(
|
||||||
<Tooltip title={isPc ? intl.get('重新安装') : ''}>
|
record.status,
|
||||||
<a onClick={() => reInstallDependence(record, index)}>
|
) ? (
|
||||||
<BugOutlined />
|
<Tooltip title={isPc ? intl.get('取消安装') : ''}>
|
||||||
</a>
|
<a onClick={() => cancelDependence(record)}>
|
||||||
</Tooltip>
|
<IconFont type="ql-icon-quxiaoanzhuang" />
|
||||||
|
</a>
|
||||||
|
</Tooltip>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Tooltip title={isPc ? intl.get('重新安装') : ''}>
|
||||||
|
<a onClick={() => reInstallDependence(record, index)}>
|
||||||
|
<BugOutlined />
|
||||||
|
</a>
|
||||||
|
</Tooltip>
|
||||||
|
{Status.已安装 === record.status && (
|
||||||
<Tooltip title={isPc ? intl.get('删除') : ''}>
|
<Tooltip title={isPc ? intl.get('删除') : ''}>
|
||||||
<a onClick={() => deleteDependence(record, index)}>
|
<a onClick={() => deleteDependence(record, index)}>
|
||||||
<DeleteOutlined />
|
<DeleteOutlined />
|
||||||
</a>
|
</a>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title={isPc ? intl.get('强制删除') : ''}>
|
)}
|
||||||
<a onClick={() => deleteDependence(record, index, true)}>
|
<Tooltip title={isPc ? intl.get('强制删除') : ''}>
|
||||||
<DeleteFilled />
|
<a onClick={() => deleteDependence(record, index, true)}>
|
||||||
</a>
|
<DeleteFilled />
|
||||||
</Tooltip>
|
</a>
|
||||||
</>
|
</Tooltip>
|
||||||
)}
|
</>
|
||||||
|
)}
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -200,11 +242,15 @@ const Dependence = () => {
|
|||||||
const tableRef = useRef<HTMLDivElement>(null);
|
const tableRef = useRef<HTMLDivElement>(null);
|
||||||
const tableScrollHeight = useTableScrollHeight(tableRef, 59);
|
const tableScrollHeight = useTableScrollHeight(tableRef, 59);
|
||||||
|
|
||||||
const getDependencies = () => {
|
const getDependencies = (status?: number[]) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
request
|
request
|
||||||
.get(
|
.get(
|
||||||
`${config.apiPrefix}dependencies?searchValue=${searchText}&type=${type}`,
|
`${
|
||||||
|
config.apiPrefix
|
||||||
|
}dependencies?searchValue=${searchText}&type=${type}&status=${
|
||||||
|
status || ''
|
||||||
|
}`,
|
||||||
)
|
)
|
||||||
.then(({ code, data }) => {
|
.then(({ code, data }) => {
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
@@ -289,6 +335,31 @@ const Dependence = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cancelDependence = (record: any) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: intl.get('确认取消安装'),
|
||||||
|
content: (
|
||||||
|
<>
|
||||||
|
{intl.get('确认取消安装')}{' '}
|
||||||
|
<Text style={{ wordBreak: 'break-all' }} type="warning">
|
||||||
|
{record.name}
|
||||||
|
</Text>{' '}
|
||||||
|
{intl.get('吗')}
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
onOk() {
|
||||||
|
request
|
||||||
|
.put(`${config.apiPrefix}dependencies/cancel`, [record.id])
|
||||||
|
.then(() => {
|
||||||
|
getDependencies();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onCancel() {
|
||||||
|
console.log('Cancel');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleCancel = (dependence?: any[]) => {
|
const handleCancel = (dependence?: any[]) => {
|
||||||
setIsModalVisible(false);
|
setIsModalVisible(false);
|
||||||
dependence && handleDependence(dependence);
|
dependence && handleDependence(dependence);
|
||||||
@@ -420,7 +491,7 @@ const Dependence = () => {
|
|||||||
}
|
}
|
||||||
return _result;
|
return _result;
|
||||||
});
|
});
|
||||||
}, 5000);
|
}, 300);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -538,6 +609,9 @@ const Dependence = () => {
|
|||||||
size="middle"
|
size="middle"
|
||||||
scroll={{ x: 768, y: tableScrollHeight }}
|
scroll={{ x: 768, y: tableScrollHeight }}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
|
onChange={(pagination, filters) => {
|
||||||
|
getDependencies(filters?.status as number[]);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</DndProvider>
|
</DndProvider>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
import { PageLoading } from '@ant-design/pro-layout';
|
import { PageLoading } from '@ant-design/pro-layout';
|
||||||
import Ansi from 'ansi-to-react';
|
import Ansi from 'ansi-to-react';
|
||||||
import WebSocketManager from '@/utils/websocket';
|
import WebSocketManager from '@/utils/websocket';
|
||||||
|
import { Status } from './type';
|
||||||
|
|
||||||
const DependenceLogModal = ({
|
const DependenceLogModal = ({
|
||||||
dependence,
|
dependence,
|
||||||
@@ -96,7 +97,11 @@ const DependenceLogModal = ({
|
|||||||
|
|
||||||
const handleMessage = (payload: any) => {
|
const handleMessage = (payload: any) => {
|
||||||
const { message, references } = payload;
|
const { message, references } = payload;
|
||||||
if (references.length > 0 && references.includes(dependence.id)) {
|
if (
|
||||||
|
references.length > 0 &&
|
||||||
|
references.includes(dependence.id) &&
|
||||||
|
[Status.删除中, Status.安装中].includes(dependence.status)
|
||||||
|
) {
|
||||||
if (message.includes('结束时间')) {
|
if (message.includes('结束时间')) {
|
||||||
setExecuting(false);
|
setExecuting(false);
|
||||||
setIsRemoveFailed(message.includes('删除失败'));
|
setIsRemoveFailed(message.includes('删除失败'));
|
||||||
@@ -108,11 +113,13 @@ const DependenceLogModal = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const ws = WebSocketManager.getInstance();
|
const ws = WebSocketManager.getInstance();
|
||||||
ws.subscribe('installDependence', handleMessage);
|
ws.subscribe('installDependence', handleMessage);
|
||||||
|
ws.subscribe('uninstallDependence', handleMessage);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
ws.unsubscribe('installDependence', handleMessage);
|
ws.unsubscribe('installDependence', handleMessage);
|
||||||
|
ws.unsubscribe('uninstallDependence', handleMessage);
|
||||||
};
|
};
|
||||||
}, []);
|
}, [dependence]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsPhone(document.body.clientWidth < 768);
|
setIsPhone(document.body.clientWidth < 768);
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
export enum DependenceStatus {
|
||||||
|
'installing',
|
||||||
|
'installed',
|
||||||
|
'installFailed',
|
||||||
|
'removing',
|
||||||
|
'removed',
|
||||||
|
'removeFailed',
|
||||||
|
'queued',
|
||||||
|
'cancelled',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Status {
|
||||||
|
'安装中',
|
||||||
|
'已安装',
|
||||||
|
'安装失败',
|
||||||
|
'删除中',
|
||||||
|
'已删除',
|
||||||
|
'删除失败',
|
||||||
|
'队列中',
|
||||||
|
'已取消',
|
||||||
|
}
|
||||||
@@ -55,7 +55,11 @@ const Log = () => {
|
|||||||
|
|
||||||
const getLog = (node: any) => {
|
const getLog = (node: any) => {
|
||||||
request
|
request
|
||||||
.get(`${config.apiPrefix}logs/${node.title}?path=${node.parent || ''}`)
|
.get(
|
||||||
|
`${config.apiPrefix}logs/detail?file=${node.title}&path=${
|
||||||
|
node.parent || ''
|
||||||
|
}`,
|
||||||
|
)
|
||||||
.then(({ code, data }) => {
|
.then(({ code, data }) => {
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
setValue(data);
|
setValue(data);
|
||||||
@@ -64,13 +68,13 @@ const Log = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onSelect = (value: any, node: any) => {
|
const onSelect = (value: any, node: any) => {
|
||||||
setCurrentNode(node);
|
|
||||||
setSelect(value);
|
|
||||||
|
|
||||||
if (node.key === select || !value) {
|
if (node.key === select || !value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setCurrentNode(node);
|
||||||
|
setSelect(value);
|
||||||
|
|
||||||
if (node.type === 'directory') {
|
if (node.type === 'directory') {
|
||||||
setValue(intl.get('请选择日志文件'));
|
setValue(intl.get('请选择日志文件'));
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -67,7 +67,11 @@ const EditModal = ({
|
|||||||
|
|
||||||
const getDetail = (node: any) => {
|
const getDetail = (node: any) => {
|
||||||
request
|
request
|
||||||
.get(`${config.apiPrefix}scripts/${node.title}?path=${node.parent || ''}`)
|
.get(
|
||||||
|
`${config.apiPrefix}scripts/detail?file=${node.title}&path=${
|
||||||
|
node.parent || ''
|
||||||
|
}`,
|
||||||
|
)
|
||||||
.then(({ code, data }) => {
|
.then(({ code, data }) => {
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
setValue(data);
|
setValue(data);
|
||||||
|
|||||||
@@ -84,9 +84,9 @@ const Script = () => {
|
|||||||
const getDetail = (node: any) => {
|
const getDetail = (node: any) => {
|
||||||
request
|
request
|
||||||
.get(
|
.get(
|
||||||
`${config.apiPrefix}scripts/${encodeURIComponent(node.title)}?path=${
|
`${config.apiPrefix}scripts/detail?file=${encodeURIComponent(
|
||||||
node.parent || ''
|
node.title,
|
||||||
}`,
|
)}&path=${node.parent || ''}`,
|
||||||
)
|
)
|
||||||
.then(({ code, data }) => {
|
.then(({ code, data }) => {
|
||||||
if (code === 200) {
|
if (code === 200) {
|
||||||
@@ -115,13 +115,13 @@ const Script = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onSelect = (value: any, node: any) => {
|
const onSelect = (value: any, node: any) => {
|
||||||
setSelect(node.key);
|
|
||||||
setCurrentNode(node);
|
|
||||||
|
|
||||||
if (node.key === select || !value) {
|
if (node.key === select || !value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setSelect(node.key);
|
||||||
|
setCurrentNode(node);
|
||||||
|
|
||||||
if (node.type === 'directory') {
|
if (node.type === 'directory') {
|
||||||
setValue(intl.get('请选择脚本文件'));
|
setValue(intl.get('请选择脚本文件'));
|
||||||
return;
|
return;
|
||||||
@@ -380,7 +380,7 @@ const Script = () => {
|
|||||||
}, [treeDom.current, data]);
|
}, [treeDom.current, data]);
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'meta+s',
|
'mod+s',
|
||||||
(e) => {
|
(e) => {
|
||||||
if (isEditing) {
|
if (isEditing) {
|
||||||
saveFile();
|
saveFile();
|
||||||
@@ -389,6 +389,36 @@ const Script = () => {
|
|||||||
{ enableOnFormTags: ['textarea'], preventDefault: true },
|
{ enableOnFormTags: ['textarea'], preventDefault: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
useHotkeys(
|
||||||
|
'mod+d',
|
||||||
|
(e) => {
|
||||||
|
if (currentNode.title) {
|
||||||
|
deleteFile();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ preventDefault: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
useHotkeys(
|
||||||
|
'mod+o',
|
||||||
|
(e) => {
|
||||||
|
if (!isEditing) {
|
||||||
|
addFile();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ preventDefault: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
useHotkeys(
|
||||||
|
'mod+e',
|
||||||
|
(e) => {
|
||||||
|
if (currentNode.title) {
|
||||||
|
cancelEdit();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ preventDefault: true },
|
||||||
|
);
|
||||||
|
|
||||||
const action = (key: string | number) => {
|
const action = (key: string | number) => {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'save':
|
case 'save':
|
||||||
|
|||||||
@@ -62,7 +62,12 @@ const RenameModal = ({
|
|||||||
onCancel={() => handleCancel()}
|
onCancel={() => handleCancel()}
|
||||||
confirmLoading={loading}
|
confirmLoading={loading}
|
||||||
>
|
>
|
||||||
<Form form={form} layout="vertical" name="edit_name_modal">
|
<Form
|
||||||
|
form={form}
|
||||||
|
initialValues={{ name: currentNode?.title }}
|
||||||
|
layout="vertical"
|
||||||
|
name="edit_name_modal"
|
||||||
|
>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="name"
|
name="name"
|
||||||
rules={[{ required: true, message: intl.get('请输入新名称') }]}
|
rules={[{ required: true, message: intl.get('请输入新名称') }]}
|
||||||
|
|||||||
@@ -77,7 +77,11 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
content: <pre><Ansi>{lastLog}</Ansi></pre>,
|
content: (
|
||||||
|
<pre>
|
||||||
|
<Ansi>{lastLog}</Ansi>
|
||||||
|
</pre>
|
||||||
|
),
|
||||||
okText: intl.get('下载更新'),
|
okText: intl.get('下载更新'),
|
||||||
cancelText: intl.get('以后再说'),
|
cancelText: intl.get('以后再说'),
|
||||||
onOk() {
|
onOk() {
|
||||||
@@ -102,10 +106,41 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
|||||||
okButtonProps: { disabled: true },
|
okButtonProps: { disabled: true },
|
||||||
title: intl.get('下载更新中...'),
|
title: intl.get('下载更新中...'),
|
||||||
centered: true,
|
centered: true,
|
||||||
content: <pre><Ansi>{value}</Ansi></pre>,
|
content: (
|
||||||
|
<pre>
|
||||||
|
<Ansi>{value}</Ansi>
|
||||||
|
</pre>
|
||||||
|
),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const reloadSystem = (type?: string) => {
|
||||||
|
request
|
||||||
|
.put(`${config.apiPrefix}system/reload`, { type })
|
||||||
|
.then((_data: any) => {
|
||||||
|
message.success({
|
||||||
|
content: (
|
||||||
|
<span>
|
||||||
|
{intl.get('系统将在')}
|
||||||
|
<Countdown
|
||||||
|
className="inline-countdown"
|
||||||
|
format="ss"
|
||||||
|
value={Date.now() + 1000 * 30}
|
||||||
|
/>
|
||||||
|
{intl.get('秒后自动刷新')}
|
||||||
|
</span>
|
||||||
|
),
|
||||||
|
duration: 30,
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.reload();
|
||||||
|
}, 30000);
|
||||||
|
})
|
||||||
|
.catch((error: any) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const showReloadModal = () => {
|
const showReloadModal = () => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
width: 600,
|
width: 600,
|
||||||
@@ -115,30 +150,7 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
|||||||
content: intl.get('系统安装包下载成功,确认重启'),
|
content: intl.get('系统安装包下载成功,确认重启'),
|
||||||
okText: intl.get('重启'),
|
okText: intl.get('重启'),
|
||||||
onOk() {
|
onOk() {
|
||||||
request
|
reloadSystem('system');
|
||||||
.put(`${config.apiPrefix}system/reload`, { type: 'system' })
|
|
||||||
.then((_data: any) => {
|
|
||||||
message.success({
|
|
||||||
content: (
|
|
||||||
<span>
|
|
||||||
{intl.get('系统将在')}
|
|
||||||
<Countdown
|
|
||||||
className="inline-countdown"
|
|
||||||
format="ss"
|
|
||||||
value={Date.now() + 1000 * 30}
|
|
||||||
/>
|
|
||||||
{intl.get('秒后自动刷新')}
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
duration: 30,
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
window.location.reload();
|
|
||||||
}, 30000);
|
|
||||||
})
|
|
||||||
.catch((error: any) => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
onCancel() {
|
onCancel() {
|
||||||
modalRef.current.update({
|
modalRef.current.update({
|
||||||
@@ -206,6 +218,13 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
|||||||
<Button type="primary" onClick={checkUpgrade}>
|
<Button type="primary" onClick={checkUpgrade}>
|
||||||
{intl.get('检查更新')}
|
{intl.get('检查更新')}
|
||||||
</Button>
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => reloadSystem()}
|
||||||
|
style={{ marginLeft: 8 }}
|
||||||
|
>
|
||||||
|
{intl.get('重新启动')}
|
||||||
|
</Button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -105,11 +105,15 @@ const Dependence = () => {
|
|||||||
label={intl.get('代理')}
|
label={intl.get('代理')}
|
||||||
name="proxy"
|
name="proxy"
|
||||||
extra={intl.get('代理与镜像源二选一即可')}
|
extra={intl.get('代理与镜像源二选一即可')}
|
||||||
|
tooltip={{
|
||||||
|
title: intl.get('代理地址, 支持HTTP(S)/SOCK5'),
|
||||||
|
placement: 'topLeft',
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Input.Group compact>
|
<Input.Group compact>
|
||||||
<Input
|
<Input
|
||||||
placeholder={intl.get('代理地址, 支持HTTP(S)/SOCK5')}
|
placeholder={'http://1.1.1.1:8080'}
|
||||||
style={{ width: 360 }}
|
style={{ width: 250 }}
|
||||||
value={systemConfig?.dependenceProxy}
|
value={systemConfig?.dependenceProxy}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSystemConfig({
|
setSystemConfig({
|
||||||
@@ -130,11 +134,15 @@ const Dependence = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Input.Group>
|
</Input.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={intl.get('Node 软件包镜像源')} name="node">
|
<Form.Item
|
||||||
|
label={intl.get('Node 软件包镜像源')}
|
||||||
|
name="node"
|
||||||
|
tooltip={intl.get('NPM 镜像源')}
|
||||||
|
>
|
||||||
<Input.Group compact>
|
<Input.Group compact>
|
||||||
<Input
|
<Input
|
||||||
style={{ width: 360 }}
|
style={{ width: 250 }}
|
||||||
placeholder={intl.get('NPM 镜像源')}
|
placeholder={'https://registry.npmmirror.com'}
|
||||||
value={systemConfig?.nodeMirror}
|
value={systemConfig?.nodeMirror}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSystemConfig({
|
setSystemConfig({
|
||||||
@@ -155,11 +163,15 @@ const Dependence = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Input.Group>
|
</Input.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={intl.get('Python 软件包镜像源')} name="python">
|
<Form.Item
|
||||||
|
label={intl.get('Python 软件包镜像源')}
|
||||||
|
name="python"
|
||||||
|
tooltip={intl.get('PyPI 镜像源')}
|
||||||
|
>
|
||||||
<Input.Group compact>
|
<Input.Group compact>
|
||||||
<Input
|
<Input
|
||||||
style={{ width: 360 }}
|
style={{ width: 250 }}
|
||||||
placeholder={intl.get('PyPI 镜像源')}
|
placeholder={'https://pypi.doubanio.com/simple/'}
|
||||||
value={systemConfig?.pythonMirror}
|
value={systemConfig?.pythonMirror}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSystemConfig({
|
setSystemConfig({
|
||||||
@@ -180,13 +192,15 @@ const Dependence = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Input.Group>
|
</Input.Group>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={intl.get('Linux 软件包镜像源')} name="linux">
|
<Form.Item
|
||||||
|
label={intl.get('Linux 软件包镜像源')}
|
||||||
|
name="linux"
|
||||||
|
tooltip={intl.get('alpine linux 镜像源')}
|
||||||
|
>
|
||||||
<Input.Group compact>
|
<Input.Group compact>
|
||||||
<Input
|
<Input
|
||||||
style={{ width: 360 }}
|
style={{ width: 250 }}
|
||||||
placeholder={intl.get(
|
placeholder={'https://mirrors.aliyun.com'}
|
||||||
'alpine linux 镜像源, 例如 https://mirrors.aliyun.com',
|
|
||||||
)}
|
|
||||||
value={systemConfig?.linuxMirror}
|
value={systemConfig?.linuxMirror}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setSystemConfig({
|
setSystemConfig({
|
||||||
|
|||||||
+17
-10
@@ -75,11 +75,19 @@ const Setting = () => {
|
|||||||
title: intl.get('权限'),
|
title: intl.get('权限'),
|
||||||
dataIndex: 'scopes',
|
dataIndex: 'scopes',
|
||||||
key: 'scopes',
|
key: 'scopes',
|
||||||
width: '40%',
|
width: 500,
|
||||||
render: (text: string, record: any) => {
|
render: (text: string, record: any) => {
|
||||||
return record.scopes.map((scope: any) => {
|
return (
|
||||||
return <Tag key={scope}>{(config.scopesMap as any)[scope]}</Tag>;
|
<div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
|
||||||
});
|
{record.scopes.map((scope: any) => {
|
||||||
|
return (
|
||||||
|
<Tag style={{ marginRight: 0 }} key={scope}>
|
||||||
|
{(config.scopesMap as any)[scope]}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -348,7 +356,9 @@ const Setting = () => {
|
|||||||
{
|
{
|
||||||
key: 'syslog',
|
key: 'syslog',
|
||||||
label: intl.get('系统日志'),
|
label: intl.get('系统日志'),
|
||||||
children: <SystemLog data={systemLogData} height={height} theme={theme}/>,
|
children: (
|
||||||
|
<SystemLog data={systemLogData} height={height} theme={theme} />
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'login',
|
key: 'login',
|
||||||
@@ -358,16 +368,13 @@ const Setting = () => {
|
|||||||
{
|
{
|
||||||
key: 'dependence',
|
key: 'dependence',
|
||||||
label: intl.get('依赖设置'),
|
label: intl.get('依赖设置'),
|
||||||
children: <Dependence />
|
children: <Dependence />,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'other',
|
key: 'other',
|
||||||
label: intl.get('其他设置'),
|
label: intl.get('其他设置'),
|
||||||
children: (
|
children: (
|
||||||
<Other
|
<Other reloadTheme={reloadTheme} systemInfo={systemInfo} />
|
||||||
reloadTheme={reloadTheme}
|
|
||||||
systemInfo={systemInfo}
|
|
||||||
/>
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
+6
-27
@@ -1,28 +1,7 @@
|
|||||||
version: 2.17.0
|
version: 2.17.2
|
||||||
changeLogLink: https://t.me/jiao_long/401
|
changeLogLink: https://t.me/jiao_long/403
|
||||||
publishTime: 2024-01-17 23:00
|
publishTime: 2024-03-02 17:00
|
||||||
changeLog: |
|
changeLog: |
|
||||||
1. 系统设置增加依赖代理和镜像源设置
|
1. 依赖管理支持队列中依赖取消安装,支持状态筛选
|
||||||
2. 更新 python 版本为 3.11
|
2. 修复 webhook 通知 body 拆分逻辑
|
||||||
3. webhook 通知 body 增加 text/plain 类型,修复多定时任务服务重启未初始化
|
3. 企业微信有长度限制,超长的进行分段提交 https://github.com/pharaoh2012
|
||||||
4. 重新安装依赖时不检查是否已安装
|
|
||||||
5. 配置管理、脚本管理增加双击目录进入编辑,ctrl/cmd + s 保存文件,感谢 https://github.com/luckrnx09
|
|
||||||
6. 系统设置增加依赖代理和镜像设置
|
|
||||||
7. 通知参数 TG_API_HOST 改为以 http 开头
|
|
||||||
8. 修改对比工具数据源,修复编辑器语言
|
|
||||||
9. 修改获取登录 ip 和 ip 地址方式
|
|
||||||
10. 修复备份数据 60 秒中断
|
|
||||||
11. 移除 config.sh 中 PipMirror 和 NpmMirror 配置
|
|
||||||
12. 修复健康检查命令
|
|
||||||
13. JavaScript 通知文件 tunnel 替换为 hpagent,移除 scripts 目录下 package.json
|
|
||||||
14. 日志和脚本增加文件大小展示,修改脚本管理列表排序
|
|
||||||
15. 修复 notify.js smtp 通知
|
|
||||||
16. 修改 schedule 服务代理环境变量
|
|
||||||
17. 修复任务详情脚本行数展示
|
|
||||||
18. 修复自定义通知 body 中 key 被自动转为小写
|
|
||||||
19. 修复初始化设置通知 shell 映射,邮箱通知错误提示
|
|
||||||
20. 修复邮件服务支持列表链接失效,感谢 https://github.com/Tunglies
|
|
||||||
21. 修复 chronocat 通知成功判断,感谢 https://github.com/youfak
|
|
||||||
22. 修复 chronocat 调用就结束执行的问题,感谢 https://github.com/6dylan6
|
|
||||||
23. 移除随机延迟相关配置及 ProxyUrl 默认值,修复拉库通知可能失败
|
|
||||||
24. 其他 bug 修复
|
|
||||||
|
|||||||
Reference in New Issue
Block a user