删除订阅支持自动删除任务和脚本

This commit is contained in:
whyour 2023-07-30 21:15:46 +08:00
parent 2e27d4057e
commit b4e5db9da9
8 changed files with 59 additions and 11 deletions

View File

@ -210,12 +210,16 @@ export default (app: Router) => {
'/',
celebrate({
body: Joi.array().items(Joi.number().required()),
query: Joi.object({
force: Joi.boolean().optional(),
t: Joi.number()
})
}),
async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger');
try {
const subscriptionService = Container.get(SubscriptionService);
const data = await subscriptionService.remove(req.body);
const data = await subscriptionService.remove(req.body, req.query);
return res.send({ code: 200, data });
} catch (e) {
return next(e);

View File

@ -16,10 +16,11 @@ import {
killTask,
handleLogPath,
promiseExec,
emptyDir,
} from '../config/util';
import { promises, existsSync } from 'fs';
import { FindOptions, Op } from 'sequelize';
import path from 'path';
import path, { join } from 'path';
import ScheduleService, { TaskCallbacks } from './schedule';
import { SimpleIntervalSchedule } from 'toad-scheduler';
import SockService from './sock';
@ -27,6 +28,8 @@ import SshKeyService from './sshKey';
import dayjs from 'dayjs';
import { LOG_END_SYMBOL } from '../config/const';
import { formatCommand, formatUrl } from '../config/subscription';
import { CrontabModel } from '../data/cron';
import CrontabService from './cron';
@Service()
export default class SubscriptionService {
@ -35,7 +38,8 @@ export default class SubscriptionService {
private scheduleService: ScheduleService,
private sockService: SockService,
private sshKeyService: SshKeyService,
) {}
private crontabService: CrontabService,
) { }
public async list(searchText?: string): Promise<Subscription[]> {
let query = {};
@ -253,13 +257,24 @@ export default class SubscriptionService {
);
}
public async remove(ids: number[]) {
public async remove(ids: number[], query: any) {
const docs = await SubscriptionModel.findAll({ where: { id: ids } });
for (const doc of docs) {
await this.handleTask(doc, false);
}
await SubscriptionModel.destroy({ where: { id: ids } });
await this.setSshConfig();
if (query?.force === true) {
const crons = await CrontabModel.findAll({ where: { sub_id: ids } });
if (crons?.length) {
await this.crontabService.remove(crons.map(x => x.id!))
}
for (const doc of docs) {
const filePath = join(config.scriptPath, doc.alias);
emptyDir(filePath);
}
}
}
public async getDb(

View File

@ -332,7 +332,7 @@ select:-webkit-autofill:focus {
}
.ant-pro-sider-logo {
padding-inline: 8px !important;
padding-inline: 5px !important;
.title {
display: flex;

View File

@ -394,5 +394,18 @@
"强制删除": "Force Delete",
"全部任务": "All Tasks",
"关联订阅": "Associate Subscription",
"订阅": "Subscription"
"订阅": "Subscription",
"创建": "Create",
"创建订阅成功": "Subscription created successfully",
"gotify的url地址,例如 https://push.example.de:8080": "Gotify URL address, e.g., https://push.example.de:8080",
"BARK推送图标,自定义推送图标 (需iOS15或以上才能显示)": "BARK push icon, custom push icon (requires iOS 15 or above to display)",
"BARK推送铃声,铃声列表去APP查看复制填写": "BARK push ringtone, check the ringtone list in the APP and copy it",
"BARK推送消息的分组, 默认为qinglong": "BARK push message grouping, default is qinglong",
"telegram代理配置认证参数, 用户名与密码用英文冒号连接 user:password": "Telegram proxy configuration authentication parameters, connect username and password with a colon, e.g., user:password",
"企业微信机器人的 webhook(详见文档 https://work.weixin.qq.com/api/doc/90000/90136/91770)例如693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa": "WeChat Work Bot webhook (see documentation at https://work.weixin.qq.com/api/doc/90000/90136/91770), e.g., 693a91f6-7xxx-4bc4-97a0-0ec2sifa5aaa",
"corpid,corpsecret,touser(注:多个成员ID使用|隔开),agentid,消息类型(选填,不填默认文本消息类型) 注意用,号隔开(英文输入法的逗号)例如wwcfrs,B-76WERQ,qinglong,1000001,2COat": "corpid, corpsecret, touser (note: separate multiple member IDs with |), agentid, message type (optional, defaults to text message type) separated by commas (`,`), e.g., wwcfrs, B-76WERQ, qinglong, 1000001, 2COat",
"密钥key,智能微秘书个人中心获取apikey申请地址https://wechat.aibotk.com/signup?from=ql": "Key, obtain the API key from the Smart WeChat Assistant's personal center, apply at: https://wechat.aibotk.com/signup?from=ql",
"一对多推送的“群组编码”(一对多推送下面->您的群组(如无则新建)->群组编码,如果您是创建群组人。也需点击“查看二维码”扫描绑定,否则不能接受群组消息推送)": "The 'Group Code' for one-to-many push (under one-to-many push->Your Group (create one if none exists)->Group Code. If you are the creator of the group, you also need to click 'View QR Code' for scanning and binding, otherwise you cannot receive group message push)",
"同时删除关联任务和脚本": "Delete associated tasks and scripts as well",
"夹及其子文件": "Folder and its sub-files"
}

View File

@ -394,5 +394,7 @@
"强制删除": "强制删除",
"全部任务": "全部任务",
"关联订阅": "关联订阅",
"订阅": "订阅"
"订阅": "订阅",
"创建": "创建",
"同时删除关联任务和脚本": "同时删除关联任务和脚本"
}

View File

@ -106,7 +106,7 @@ const Dependence = () => {
{
title: intl.get('状态'),
key: 'status',
width: 100,
width: 120,
dataIndex: 'status',
render: (text: string, record: any, index: number) => {
return (

View File

@ -195,7 +195,7 @@ const EditModal = ({
>
{intl.get('清空日志')}
</Button>
<Button
{/* <Button
type="primary"
style={{ marginRight: 8 }}
onClick={() => {
@ -203,7 +203,7 @@ const EditModal = ({
}}
>
{intl.get('设置')}
</Button>
</Button> */}
<Button
type="primary"
style={{ marginRight: 8 }}

View File

@ -12,6 +12,7 @@ import {
Typography,
Input,
Tooltip,
Checkbox,
} from 'antd';
import {
ClockCircleOutlined,
@ -240,6 +241,7 @@ const Subscription = () => {
const [logSubscription, setLogSubscription] = useState<any>();
const tableRef = useRef<HTMLDivElement>(null);
const tableScrollHeight = useTableScrollHeight(tableRef);
const deleteCheckRef = useRef(false);
const runSubscription = (record: any, index: number) => {
Modal.confirm({
@ -335,6 +337,10 @@ const Subscription = () => {
setIsModalVisible(true);
};
const onCheckChange = (e) => {
deleteCheckRef.current = e.target.checked;
};
const delSubscription = (record: any, index: number) => {
Modal.confirm({
title: intl.get('确认删除'),
@ -345,11 +351,19 @@ const Subscription = () => {
{record.name}
</Text>{' '}
{intl.get('吗')}
<div style={{ marginTop: 20 }}>
<Checkbox onChange={onCheckChange}>
{intl.get('同时删除关联任务和脚本')}
</Checkbox>
</div>
</>
),
onOk() {
request
.delete(`${config.apiPrefix}subscriptions`, { data: [record.id] })
.delete(`${config.apiPrefix}subscriptions`, {
data: [record.id],
params: { force: deleteCheckRef.current },
})
.then(({ code, data }) => {
if (code === 200) {
message.success('删除成功');