Compare commits

...

42 Commits

Author SHA1 Message Date
whyour c746a3d215 修复.env 2022-01-30 20:22:00 +08:00
whyour 548d924fa0 更新版本 v2.11.2 2022-01-30 18:25:18 +08:00
whyour 18a6be3ecd 修改placeholder 2022-01-30 17:39:27 +08:00
whyour afef0cb72f 更新dockerfile 2022-01-30 14:59:41 +08:00
whyour 1221b47eca 修改dockerfile 2022-01-30 14:03:57 +08:00
whyour a356eeb5da 修改base context 2022-01-30 12:37:20 +08:00
whyour 25bb0972b9 修改dockerfile 2022-01-30 12:31:49 +08:00
whyour 0914075cf6 修改定时任务唯一键 2022-01-30 10:11:47 +08:00
whyour 74b258e1b6 修改定时任务排序 2022-01-30 09:59:33 +08:00
whyour 27eb0a21e4 修改dockerfile 2022-01-29 14:23:19 +08:00
whyour d77c6d50d8 修改dockerfile 2022-01-29 12:53:21 +08:00
whyour 6a64c18a7b 修改dockerfile 2022-01-29 12:15:25 +08:00
whyour b97ff714ae 修复dockerfile 2022-01-29 11:45:06 +08:00
whyour 1f23eea805 更新dockerfile 2022-01-29 11:20:43 +08:00
whyour cb0cb7df21 修改dockerfile 2022-01-29 00:09:37 +08:00
whyour f3e8628664 移除prepare scripts 2022-01-28 23:46:17 +08:00
whyour 4758471f9f 修改sentry依赖 2022-01-28 23:19:39 +08:00
whyour c10bd5a549 修改sentry cli版本 2022-01-28 23:14:12 +08:00
whyour d53faf96eb 修改sentry依赖 2022-01-28 22:47:46 +08:00
whyour 2307b8ed1a 增加esbuild 2022-01-28 21:53:05 +08:00
whyour 711af8d4a5 修改dockfile 2022-01-28 20:54:00 +08:00
whyour 458c9c456b 修改dockerfile 2022-01-28 20:27:38 +08:00
whyour 29069df48c 修复dockerfile 2022-01-28 19:33:01 +08:00
whyour 300e84ae2c 修改dockerfile 2022-01-28 19:23:57 +08:00
whyour bf11768b92 修改base镜像 2022-01-27 23:09:29 +08:00
whyour 91bd1d9263 测试青龙基础镜像 2022-01-27 23:06:35 +08:00
whyour ac40f9ff12 测试最新alpine 2022-01-27 22:21:34 +08:00
whyour f930837220 修复获取克隆仓库状态 2022-01-27 22:15:45 +08:00
whyour 1d5e3acc93 去除sql执行日志 2022-01-27 00:56:37 +08:00
whyour 2aec1f9846 修改表唯一约束 2022-01-27 00:49:44 +08:00
whyour b56a681b98 python默认实时输出 2022-01-25 23:03:56 +08:00
whyour 2713419b32 修复修改任务状态本地免认证 2022-01-25 22:52:27 +08:00
whyour 764a3492cc 添加关于页 2022-01-24 23:17:12 +08:00
whyour 29fc471ac4 修复日志加载状态 2022-01-24 22:50:01 +08:00
whyour 54a597aad3 修改logo地址 2022-01-23 16:55:11 +08:00
whyour 778961d0b6 修改node基础镜像版本 2022-01-22 22:09:16 +08:00
whyour 14b01ac761 测试基础镜像node版本 2022-01-22 21:57:02 +08:00
whyour f87848c05b 修改darkreader版本 2022-01-22 21:09:01 +08:00
whyour 153e5a806d 增加sqlite连接池 2022-01-22 20:53:22 +08:00
whyour ee1b8a906f 移除cdn依赖 2022-01-22 20:25:22 +08:00
whyour 734685d45a 定时任务默认改为创建时间倒序 2022-01-21 22:38:13 +08:00
whyour e3b540c212 修复更新系统通知 2022-01-21 22:27:50 +08:00
34 changed files with 8723 additions and 8656 deletions
+2 -1
View File
@@ -2,7 +2,8 @@ MONGODB_URI='mongodb://'
YIYAN_MONGODB_URI=''
CRON_PORT=5500
PORT=5600
BACK_PORT=5600
PORT=5700
LOG_LEVEL='debug'
+59
View File
@@ -0,0 +1,59 @@
name: Build QL BASE
on:
schedule:
- cron: '00 18 * * *' # GMT 14:00 => 北京时间 2:00
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: '14'
- name: Set time zone
uses: szenius/set-timezone@v1.0
with:
timezoneLinux: "Asia/Shanghai"
timezoneMacos: "Asia/Shanghai"
timezoneWindows: "China Standard Time"
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to GHCR
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Build and push
id: docker_build
uses: docker/build-push-action@v2
with:
build-args: |
MAINTAINER=${{ github.repository_owner }}
QL_BRANCH=${{ github.ref_name }}
platforms: linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64,linux/s390x
context: .
file: docker/base/Dockerfile
push: true
tags: whyour/ql:base
+2 -2
View File
@@ -28,8 +28,8 @@ jobs:
- name: build front and back
run: |
yarn install
yarn build
yarn build-back
yarn build:front
yarn build:back
- name: copy to static repo
env:
-9
View File
@@ -32,18 +32,9 @@ export default defineConfig({
externals: {
react: 'window.React',
'react-dom': 'window.ReactDOM',
darkreader: 'window.DarkReader',
codemirror: 'window.CodeMirror',
'sockjs-client': 'window.SockJS',
},
scripts: [
'https://gw.alipayobjects.com/os/lib/react/16.13.1/umd/react.production.min.js',
'https://gw.alipayobjects.com/os/lib/react-dom/16.13.1/umd/react-dom.production.min.js',
'https://unpkg.zhimg.com/darkreader@4.9.40/darkreader.js',
'https://unpkg.zhimg.com/codemirror@5/lib/codemirror.js',
'https://unpkg.zhimg.com/codemirror@5/mode/shell/shell.js',
'https://unpkg.zhimg.com/codemirror@5/mode/python/python.js',
'https://unpkg.zhimg.com/codemirror@5/mode/javascript/javascript.js',
'https://unpkg.zhimg.com/sockjs-client@1/dist/sockjs.min.js',
],
});
+1 -2
View File
@@ -153,11 +153,10 @@ $ git clone git@github.com:whyour/qinglong.git
$ cd qinglong
$ cp .env.example .env
$ yarn install
$ yarn start-back
$ yarn start
```
打开你的浏览器,访问 http://127.0.0.1:5601
打开你的浏览器,访问 http://127.0.0.1:5700
## 交流
+1 -1
View File
@@ -37,7 +37,7 @@ if (envFound.error) {
}
export default {
port: parseInt(process.env.PORT as string, 10),
port: parseInt(process.env.BACK_PORT as string, 10),
cronPort: parseInt(process.env.CRON_PORT as string, 10),
secret: process.env.SECRET || createRandomString(16, 32),
logs: {
+10 -4
View File
@@ -49,12 +49,18 @@ export enum CrontabStatus {
interface CronInstance extends Model<Crontab, Crontab>, Crontab {}
export const CrontabModel = sequelize.define<CronInstance>('Crontab', {
name: DataTypes.STRING,
command: {
unique: 'command',
name: {
unique: 'compositeIndex',
type: DataTypes.STRING,
},
command: {
unique: 'compositeIndex',
type: DataTypes.STRING,
},
schedule: {
unique: 'compositeIndex',
type: DataTypes.STRING,
},
schedule: DataTypes.STRING,
timestamp: DataTypes.STRING,
saved: DataTypes.BOOLEAN,
status: DataTypes.NUMBER,
+2 -2
View File
@@ -30,10 +30,10 @@ export const initEnvPosition = 9999999999;
interface EnvInstance extends Model<Env, Env>, Env {}
export const EnvModel = sequelize.define<EnvInstance>('Env', {
value: DataTypes.STRING,
value: { type: DataTypes.STRING, unique: 'compositeIndex' },
timestamp: DataTypes.STRING,
status: DataTypes.NUMBER,
position: DataTypes.NUMBER,
name: DataTypes.STRING,
name: { type: DataTypes.STRING, unique: 'compositeIndex' },
remarks: DataTypes.STRING,
});
+7
View File
@@ -5,4 +5,11 @@ export const sequelize = new Sequelize({
dialect: 'sqlite',
storage: `${config.dbPath}database.sqlite`,
logging: false,
pool: {
max: 6,
min: 0,
idle: 30000,
},
});
export type ResponseType<T> = { code: number; data?: T; message?: string };
+1 -1
View File
@@ -35,7 +35,7 @@ export enum CrontabStatus {
interface AppInstance extends Model<App, App>, App {}
export const AppModel = sequelize.define<AppInstance>('App', {
name: DataTypes.STRING,
name: { type: DataTypes.STRING, unique: 'name' },
scopes: DataTypes.JSON,
client_id: DataTypes.STRING,
client_secret: DataTypes.STRING,
+11 -1
View File
@@ -11,7 +11,17 @@ import { sequelize } from '../data';
export default async () => {
try {
await sequelize.sync({ alter: true });
await sequelize.sync();
await new Promise((resolve) => setTimeout(() => resolve(null), 5000));
// try {
// const queryInterface = sequelize.getQueryInterface();
// await queryInterface.addIndex('Crontabs', ['command'], { unique: true });
// await queryInterface.addIndex('Envs', ['name', 'value'], { unique: true });
// await queryInterface.addIndex('Apps', ['name'], { unique: true });
// } catch (error) {
// }
const crondbExist = await fileExist(config.cronDbFile);
const dependenceDbExist = await fileExist(config.dependenceDbFile);
+5 -4
View File
@@ -68,18 +68,19 @@ export default ({ app }: { app: Application }) => {
}
}
const originPath = `${req.baseUrl}${req.path === '/' ? '' : req.path}`;
if (
!headerToken &&
req.path &&
config.apiWhiteList.includes(req.path) &&
req.path !== '/api/crons/status'
originPath &&
config.apiWhiteList.includes(originPath) &&
originPath !== '/api/crons/status'
) {
return next();
}
const remoteAddress = req.socket.remoteAddress;
if (
remoteAddress === '::ffff:127.0.0.1' &&
req.path === '/api/crons/status'
originPath === '/api/crons/status'
) {
return next();
}
+4 -9
View File
@@ -5,7 +5,7 @@ import { Crontab, CrontabModel, CrontabStatus } from '../data/cron';
import { exec, execSync, spawn } from 'child_process';
import fs from 'fs';
import cron_parser from 'cron-parser';
import { getFileContentByName, concurrentRun } from '../config/util';
import { getFileContentByName, concurrentRun, fileExist } from '../config/util';
import { promises, existsSync } from 'fs';
import { promisify } from 'util';
import { Op } from 'sequelize';
@@ -31,12 +31,6 @@ export default class CronService {
}
public async insert(payload: Crontab): Promise<Crontab> {
const cron = await CrontabModel.findOne({
where: { command: payload.command },
});
if (cron) {
return cron;
}
return await CrontabModel.create(payload, { returning: true });
}
@@ -165,7 +159,7 @@ export default class CronService {
try {
const result = await CrontabModel.findAll({
where: query,
order: [['updatedAt', 'DESC']],
order: [['createdAt', 'DESC']],
});
return result as any;
} catch (error) {
@@ -200,7 +194,8 @@ export default class CronService {
}
}
const err = await this.killTask(doc.command);
if (doc.log_path) {
const logFileExist = await fileExist(doc.log_path);
if (doc.log_path && logFileExist) {
const str = err ? `\n${err}` : '';
fs.appendFileSync(
`${doc.log_path}`,
+6 -2
View File
@@ -28,8 +28,12 @@ export default class EnvService {
}
public async insert(payloads: Env[]): Promise<Env[]> {
const docs = await EnvModel.bulkCreate(payloads);
return docs;
const result = [];
for (const env of payloads) {
const doc = await EnvModel.create(env, { returning: true });
result.push(doc);
}
return result;
}
public async update(payload: Env): Promise<Env> {
+2 -2
View File
@@ -24,8 +24,8 @@ export default class OpenService {
return { ...doc, tokens: [] };
}
public async insert(payloads: App): Promise<App> {
const doc = await AppModel.create(payloads, { returning: true });
public async insert(payload: App): Promise<App> {
const doc = await AppModel.create(payload, { returning: true });
return doc.get({ plain: true }) as App;
}
+2 -2
View File
@@ -86,9 +86,9 @@ export default class SystemService {
let lastLog = '';
try {
const result = await Promise.race([
got.get(config.lastVersionFile, { timeout: 1000, retry: 0 }),
got.get(config.lastVersionFile, { timeout: 6000, retry: 0 }),
got.get(`https://ghproxy.com/${config.lastVersionFile}`, {
timeout: 5000,
timeout: 6000,
retry: 0,
}),
]);
+10 -2
View File
@@ -313,8 +313,16 @@ export default class UserService {
}
private async updateAuthDb(payload: AuthInfo): Promise<any> {
await AuthModel.upsert({ ...payload });
const doc = await this.getDb({ type: payload.type });
let doc = await AuthModel.findOne({ type: payload.type });
if (doc) {
const updateResult = await AuthModel.update(payload, {
where: { id: doc.id },
returning: true,
});
doc = updateResult[1][0];
} else {
doc = await AuthModel.create(payload, { returning: true });
}
return doc;
}
+8 -33
View File
@@ -1,53 +1,28 @@
FROM node:lts-alpine3.12
FROM whyour/ql:base
ARG QL_MAINTAINER="whyour"
LABEL maintainer="${QL_MAINTAINER}"
ARG QL_URL=https://github.com/${QL_MAINTAINER}/qinglong.git
ARG QL_BRANCH=master
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
LANG=zh_CN.UTF-8 \
SHELL=/bin/bash \
PS1="\u@\h:\w \$ " \
QL_DIR=/ql \
QL_BRANCH=${QL_BRANCH}
WORKDIR ${QL_DIR}
RUN set -x \
&& sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories \
&& apk update -f \
&& apk upgrade \
&& apk --no-cache add -f bash \
coreutils \
moreutils \
git \
curl \
wget \
tzdata \
perl \
openssl \
nginx \
python3 \
jq \
openssh \
py3-pip \
python2 \
g++ \
make \
&& rm -rf /var/cache/apk/* \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone \
&& touch ~/.bashrc \
&& git clone -b ${QL_BRANCH} ${QL_URL} ${QL_DIR} \
&& git config --global user.email "qinglong@@users.noreply.github.com" \
&& git config --global user.name "qinglong" \
RUN git clone -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 \
&& npm install -g pnpm \
&& pnpm install -g pm2 \
&& pnpm install -g ts-node typescript tslib \
&& rm -rf /root/.npm \
&& cp -rf /node_modules ./ \
&& rm -rf /node_modules \
&& pnpm install --prod \
&& rm -rf /root/.pnpm-store \
&& rm -rf /root/.cache \
&& git clone -b ${QL_BRANCH} https://github.com/${QL_MAINTAINER}/qinglong-static.git /static \
&& cp -rf /static/* ${QL_DIR} \
&& rm -rf /static
+49
View File
@@ -0,0 +1,49 @@
FROM node:alpine
ARG QL_MAINTAINER="whyour"
LABEL maintainer="${QL_MAINTAINER}"
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
LANG=zh_CN.UTF-8 \
SHELL=/bin/bash \
PS1="\u@\h:\w \$ "
COPY package.json /
RUN set -x \
&& sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' /etc/apk/repositories \
&& apk update -f \
&& apk upgrade \
&& apk --no-cache add -f bash \
coreutils \
moreutils \
git \
curl \
wget \
tzdata \
perl \
openssl \
nginx \
python3 \
jq \
openssh \
py3-pip \
python2 \
g++ \
make \
&& rm -rf /var/cache/apk/* \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone \
&& touch ~/.bashrc \
&& git config --global user.email "qinglong@@users.noreply.github.com" \
&& git config --global user.name "qinglong" \
&& npm install -g pnpm \
&& pnpm install -g pm2 \
&& pnpm install -g ts-node typescript tslib \
&& cd / && pnpm install --prod \
&& apk --purge del python2 g++ make \
&& rm -rf /root/.npm \
&& rm -rf /root/.pnpm-store \
&& rm -rf /root/.cache \
&& rm -f /package.json
CMD [ "node" ]
+14 -13
View File
@@ -1,14 +1,15 @@
{
"private": true,
"scripts": {
"start": "umi dev",
"build": "umi build",
"build-back": "tsc -p tsconfig.back.json",
"start-back": "nodemon",
"panel": "npm run build-back && node build/app.js",
"schedule": "npm run build-back && node build/schedule.js",
"prepare": "umi generate tmp",
"start": "concurrently -n w: npm:start:*",
"start:front": "umi dev",
"start:back": "nodemon",
"build:front": "umi build",
"build:back": "tsc -p tsconfig.back.json",
"panel": "npm run build:back && node build/app.js",
"schedule": "npm run build:back && node build/schedule.js",
"prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'",
"prepare": "umi generate tmp",
"test": "umi-test",
"test:coverage": "umi-test --coverage"
},
@@ -25,14 +26,15 @@
},
"dependencies": {
"@otplib/preset-default": "^12.0.1",
"@sentry/node": "^6.16.1",
"@sentry/tracing": "^6.16.1",
"@sentry/node": "^6.17.2",
"@sentry/tracing": "^6.17.2",
"body-parser": "^1.19.0",
"celebrate": "^13.0.3",
"chokidar": "^3.5.2",
"cors": "^2.8.5",
"cron-parser": "^3.5.0",
"dotenv": "^8.2.0",
"esbuild": "^0.14.14",
"express": "^4.17.1",
"express-jwt": "^6.0.0",
"express-urlrewrite": "^1.4.0",
@@ -60,8 +62,7 @@
"@ant-design/icons": "^4.6.2",
"@ant-design/pro-layout": "^6.26.0",
"@monaco-editor/react": "^4.3.1",
"@sentry/react": "^6.16.1",
"@sentry/webpack-plugin": "^1.18.3",
"@sentry/react": "^6.17.2",
"@types/cors": "^2.8.10",
"@types/express": "^4.17.8",
"@types/express-jwt": "^6.0.1",
@@ -84,9 +85,9 @@
"antd": "^4.17.0-alpha.6",
"codemirror": "^5.62.2",
"compression-webpack-plugin": "6.1.1",
"darkreader": "^4.9.27",
"concurrently": "^7.0.0",
"darkreader": "4.9.40",
"lint-staged": "^10.0.7",
"@mapbox/node-pre-gyp": "1.0.8",
"nodemon": "^2.0.4",
"prettier": "^2.2.0",
"qrcode.react": "^1.0.1",
+3 -2
View File
@@ -60,6 +60,7 @@ original_name=(
init_env() {
export NODE_PATH=/usr/local/bin:/usr/local/pnpm-global/5/node_modules:/usr/local/lib/node_modules
export PYTHONUNBUFFERED=1
}
import_config() {
@@ -69,6 +70,7 @@ import_config() {
command_timeout_time=${CommandTimeoutTime:-"1h"}
proxy_url=${ProxyUrl:-""}
file_extensions=${RepoFileExtensions:-"js py"}
current_branch=${QL_BRANCH}
if [[ -n "${DefaultCronRule}" ]]; then
default_cron="${DefaultCronRule}"
@@ -302,9 +304,8 @@ git_clone_scripts() {
set_proxy
git clone $part_cmd $url $dir
unset_proxy
exit_status=$?
unset_proxy
}
git_pull_scripts() {
+6 -4
View File
@@ -253,8 +253,8 @@ update_qinglong() {
local no_restart="$1"
[[ -f $dir_root/package.json ]] && ql_depend_old=$(cat $dir_root/package.json)
reset_romote_url ${dir_root} "https://github.com/whyour/qinglong.git" "master"
git_pull_scripts $dir_root "master"
reset_romote_url ${dir_root} "https://github.com/whyour/qinglong.git" ${current_branch}
git_pull_scripts $dir_root ${current_branch}
if [[ $exit_status -eq 0 ]]; then
echo -e "\n更新$dir_root成功...\n"
@@ -270,8 +270,8 @@ update_qinglong() {
local url="https://github.com/whyour/qinglong-static.git"
if [[ -d ${ql_static_repo}/.git ]]; then
reset_romote_url ${ql_static_repo} ${url} "master"
git_pull_scripts ${ql_static_repo} "master"
reset_romote_url ${ql_static_repo} ${url} ${current_branch}
git_pull_scripts ${ql_static_repo} ${current_branch}
else
git_clone_scripts ${url} ${ql_static_repo}
fi
@@ -307,6 +307,8 @@ patch_version() {
fi
git config --global pull.rebase false
cp -f /ql/.env.example /ql/.env
}
reload_pm2() {
+1 -1
View File
@@ -235,7 +235,7 @@ export default function (props: any) {
logo={
<Image
preview={false}
src="https://pic.imgdb.cn/item/61acd0dd2ab3f51d912b1986.png"
src="https://lf9-survey.bytetos.com/obj/web.business.image/202201205d0d7b5e576ee603497ab6f3"
/>
}
title={
+30 -16
View File
@@ -31,7 +31,7 @@ import {
import config from '@/utils/config';
import { PageContainer } from '@ant-design/pro-layout';
import { request } from '@/utils/http';
import CronModal,{ CronLabelModal } from './modal';
import CronModal, { CronLabelModal } from './modal';
import CronLogModal from './logModal';
import cron_parser from 'cron-parser';
import { diffTime } from '@/utils/date';
@@ -49,7 +49,7 @@ enum CrontabStatus {
'queued',
}
const CrontabSort: any = { 0: 0, 3: 1, 1: 2, 4: 3 };
const CrontabSort: any = { 0: 0, 5: 1, 3: 2, 1: 3, 4: 4 };
enum OperationName {
'启用',
@@ -94,21 +94,30 @@ const Crontab = ({ headerStyle, isPhone }: any) => {
)}
</a>
<span>
{record.labels?.length > 0 && record.labels[0] !== '' ?
<Popover placement='right' trigger={isPhone ? 'click' : 'hover'}
{record.labels?.length > 0 && record.labels[0] !== '' ? (
<Popover
placement="right"
trigger={isPhone ? 'click' : 'hover'}
content={
<div>
{record.labels?.map((label: string, i: number) => (
<Tag color="blue"
onClick={() => { onSearch(`label:${label}`) }}>
<Tag
color="blue"
onClick={() => {
onSearch(`label:${label}`);
}}
>
{label}
</Tag>
))}
</div>
}>
}
>
<Tag color="blue">{record.labels[0]}</Tag>
</Popover>
: ''}
) : (
''
)}
</span>
</>
),
@@ -381,14 +390,19 @@ const Crontab = ({ headerStyle, isPhone }: any) => {
setValue(
data.data
.sort((a: any, b: any) => {
const sortA = a.isDisabled ? 4 : a.status;
const sortB = b.isDisabled ? 4 : b.status;
a.isPinned = a.isPinned ? a.isPinned : 0;
b.isPinned = b.isPinned ? b.isPinned : 0;
if (a.isPinned === b.isPinned) {
return CrontabSort[sortA] - CrontabSort[sortB];
}
return b.isPinned - a.isPinned;
const sortA =
a.isDisabled && a.status !== 0
? 4
: a.isPinned && a.status !== 0
? 5
: a.status;
const sortB =
b.isDisabled && b.status !== 0
? 4
: b.isPinned && b.status !== 0
? 5
: b.status;
return CrontabSort[sortA] - CrontabSort[sortB];
})
.map((x) => {
return {
+1 -1
View File
@@ -90,7 +90,7 @@ const CronLogModal = ({
return (
<>
{(executing || loading) && <Loading3QuartersOutlined spin />}
{!executing && <CheckCircleOutlined />}
{!executing && !loading && <CheckCircleOutlined />}
<span style={{ marginLeft: 5 }}>-{cron && cron.name}</span>{' '}
</>
);
+1 -1
View File
@@ -233,7 +233,7 @@ const Initialization = () => {
<img
alt="logo"
className={styles.logo}
src="https://pic.imgdb.cn/item/61acd0dd2ab3f51d912b1986.png"
src="https://lf9-survey.bytetos.com/obj/web.business.image/202201205d0d7b5e576ee603497ab6f3"
/>
<span className={styles.title}></span>
</div>
+3 -1
View File
@@ -128,7 +128,7 @@ const Log = ({ headerStyle, isPhone, theme }: any) => {
value={select}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
treeData={data}
placeholder="请选择日志文件"
placeholder="请选择日志"
showSearch
onSelect={onSelect}
/>,
@@ -147,6 +147,8 @@ const Log = ({ headerStyle, isPhone, theme }: any) => {
<Input.Search
className={styles['left-tree-search']}
onChange={onSearch}
placeholder="请输入日志名"
allowClear
></Input.Search>
<div className={styles['left-tree-scroller']} ref={treeDom}>
<Tree
+1 -1
View File
@@ -135,7 +135,7 @@ const Login = () => {
<img
alt="logo"
className={styles.logo}
src="https://pic.imgdb.cn/item/61acd0dd2ab3f51d912b1986.png"
src="https://lf9-survey.bytetos.com/obj/web.business.image/202201205d0d7b5e576ee603497ab6f3"
/>
<span className={styles.title}>
{twoFactor ? '两步验证' : config.siteName}
+3 -1
View File
@@ -413,7 +413,7 @@ const Script = ({ headerStyle, isPhone, theme, socketMessage }: any) => {
value={select}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
treeData={data}
placeholder="请选择脚本文件"
placeholder="请选择脚本"
showSearch
onSelect={onSelect}
/>,
@@ -477,6 +477,8 @@ const Script = ({ headerStyle, isPhone, theme, socketMessage }: any) => {
<Input.Search
className={styles['left-tree-search']}
onChange={onSearch}
placeholder="请输入脚本名"
allowClear
></Input.Search>
<div className={styles['left-tree-scroller']} ref={treeDom}>
<Tree
+49
View File
@@ -0,0 +1,49 @@
import React, { useEffect, useState } from 'react';
import { Typography, Input, Form, Button, message } from 'antd';
import styles from './index.less';
const { Link } = Typography;
const About = () => {
return (
<div className={styles.container}>
<img
alt="logo"
style={{ width: 140, marginRight: 20 }}
src="https://lf9-survey.bytetos.com/obj/web.business.image/202201205d0d7b5e576ee603497ab6f3"
/>
<div className={styles.right}>
<span className={styles.title}></span>
<span className={styles.desc}>
python3javaScriptshelltypescript A timed
task management panel that supports typescript, javaScript, python3,
and shell.
</span>
<div>
<Link
href="https://github.com/whyour/qinglong"
target="_blank"
style={{ marginRight: 15 }}
>
Github
</Link>
<Link
href="https://t.me/jiao_long"
target="_blank"
style={{ marginRight: 15 }}
>
Telegram频道
</Link>
<Link
href="https://github.com/whyour/qinglong/issues"
target="_blank"
>
BUG
</Link>
</div>
</div>
</div>
);
};
export default About;
+20
View File
@@ -0,0 +1,20 @@
.container {
display: flex;
justify-content: center;
align-items: center;
padding: 50px 130px;
.right {
display: flex;
justify-content: center;
flex-direction: column;
.title {
font-size: 25px;
margin-bottom: 10px;
}
.desc {
margin-bottom: 10px;
}
}
}
+5 -2
View File
@@ -32,7 +32,7 @@ import SecuritySettings from './security';
import LoginLog from './loginLog';
import NotificationSetting from './notification';
import CheckUpdate from './checkUpdate';
import { useForm } from 'antd/lib/form/Form';
import About from './about';
const { Text } = Typography;
const optionsWithDisabled = [
@@ -124,7 +124,7 @@ const Setting = ({
const [loginLogData, setLoginLogData] = useState<any[]>([]);
const [notificationInfo, setNotificationInfo] = useState<any>();
const [logRemoveFrequency, setLogRemoveFrequency] = useState<number>();
const [form] = useForm();
const [form] = Form.useForm();
const themeChange = (e: any) => {
setTheme(e.target.value);
@@ -381,6 +381,9 @@ const Setting = ({
</Form.Item>
</Form>
</Tabs.TabPane>
<Tabs.TabPane tab="关于" key="about">
<About />
</Tabs.TabPane>
</Tabs>
<AppModal
visible={isModalVisible}
+10 -11
View File
@@ -1,13 +1,12 @@
export const version = '2.11.1';
export const version = '2.11.2';
export const changeLogLink = 'https://t.me/jiao_long/261';
export const changeLog = `2.11.1 版本说明
1. 修复openapi获取tokentoken认证
2. 修复环境变量搜索,排序,更新
3. 修复重置应用秘钥
4. 修复环境变量更新时间显示
5. 修复定时默认任务排序
6. task支持运行pyc文件,感谢https://github.com/chiupam
6. 移除ghproxy默认代理,增加新配置ProxyUrl,支持http或者socks代理。例如 http://127.0.0.1:7890
7. 更换JavaScript cdn地址
8. 其他bug修复
export const changeLog = `2.11.2 版本说明
1. 修复更新通知
2. 修复定时任务排序
3. 移除cdn文件
4. 修复日志加载状态
5. python任务测试实时输出
6. 修改定时任务、环境变量唯一值
6. 修复shell克隆仓库状态获取
7. 重构基础镜像,缩减镜像大小、打包时间
`;
+8394 -8525
View File
File diff suppressed because it is too large Load Diff