mirror of
				https://github.com/whyour/qinglong.git
				synced 2025-11-01 01:16:07 +08:00 
			
		
		
		
	删除订阅支持自动删除任务和脚本
This commit is contained in:
		
							parent
							
								
									2e27d4057e
								
							
						
					
					
						commit
						b4e5db9da9
					
				|  | @ -210,12 +210,16 @@ export default (app: Router) => { | ||||||
|     '/', |     '/', | ||||||
|     celebrate({ |     celebrate({ | ||||||
|       body: Joi.array().items(Joi.number().required()), |       body: Joi.array().items(Joi.number().required()), | ||||||
|  |       query: Joi.object({ | ||||||
|  |         force: Joi.boolean().optional(), | ||||||
|  |         t: Joi.number() | ||||||
|  |       }) | ||||||
|     }), |     }), | ||||||
|     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 { | ||||||
|         const subscriptionService = Container.get(SubscriptionService); |         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 }); |         return res.send({ code: 200, data }); | ||||||
|       } catch (e) { |       } catch (e) { | ||||||
|         return next(e); |         return next(e); | ||||||
|  |  | ||||||
|  | @ -16,10 +16,11 @@ import { | ||||||
|   killTask, |   killTask, | ||||||
|   handleLogPath, |   handleLogPath, | ||||||
|   promiseExec, |   promiseExec, | ||||||
|  |   emptyDir, | ||||||
| } from '../config/util'; | } from '../config/util'; | ||||||
| import { promises, existsSync } from 'fs'; | import { promises, existsSync } from 'fs'; | ||||||
| import { FindOptions, Op } from 'sequelize'; | import { FindOptions, Op } from 'sequelize'; | ||||||
| import path from 'path'; | import path, { join } from 'path'; | ||||||
| import ScheduleService, { TaskCallbacks } from './schedule'; | import ScheduleService, { TaskCallbacks } from './schedule'; | ||||||
| import { SimpleIntervalSchedule } from 'toad-scheduler'; | import { SimpleIntervalSchedule } from 'toad-scheduler'; | ||||||
| import SockService from './sock'; | import SockService from './sock'; | ||||||
|  | @ -27,6 +28,8 @@ import SshKeyService from './sshKey'; | ||||||
| import dayjs from 'dayjs'; | import dayjs from 'dayjs'; | ||||||
| import { LOG_END_SYMBOL } from '../config/const'; | import { LOG_END_SYMBOL } from '../config/const'; | ||||||
| import { formatCommand, formatUrl } from '../config/subscription'; | import { formatCommand, formatUrl } from '../config/subscription'; | ||||||
|  | import { CrontabModel } from '../data/cron'; | ||||||
|  | import CrontabService from './cron'; | ||||||
| 
 | 
 | ||||||
| @Service() | @Service() | ||||||
| export default class SubscriptionService { | export default class SubscriptionService { | ||||||
|  | @ -35,6 +38,7 @@ export default class SubscriptionService { | ||||||
|     private scheduleService: ScheduleService, |     private scheduleService: ScheduleService, | ||||||
|     private sockService: SockService, |     private sockService: SockService, | ||||||
|     private sshKeyService: SshKeyService, |     private sshKeyService: SshKeyService, | ||||||
|  |     private crontabService: CrontabService, | ||||||
|   ) { } |   ) { } | ||||||
| 
 | 
 | ||||||
|   public async list(searchText?: string): Promise<Subscription[]> { |   public async list(searchText?: string): Promise<Subscription[]> { | ||||||
|  | @ -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 } }); |     const docs = await SubscriptionModel.findAll({ where: { id: ids } }); | ||||||
|     for (const doc of docs) { |     for (const doc of docs) { | ||||||
|       await this.handleTask(doc, false); |       await this.handleTask(doc, false); | ||||||
|     } |     } | ||||||
|     await SubscriptionModel.destroy({ where: { id: ids } }); |     await SubscriptionModel.destroy({ where: { id: ids } }); | ||||||
|     await this.setSshConfig(); |     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( |   public async getDb( | ||||||
|  |  | ||||||
|  | @ -332,7 +332,7 @@ select:-webkit-autofill:focus { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .ant-pro-sider-logo { | .ant-pro-sider-logo { | ||||||
|   padding-inline: 8px !important; |   padding-inline: 5px !important; | ||||||
| 
 | 
 | ||||||
|   .title { |   .title { | ||||||
|     display: flex; |     display: flex; | ||||||
|  |  | ||||||
|  | @ -394,5 +394,18 @@ | ||||||
|   "强制删除": "Force Delete", |   "强制删除": "Force Delete", | ||||||
|   "全部任务": "All Tasks", |   "全部任务": "All Tasks", | ||||||
|   "关联订阅": "Associate Subscription", |   "关联订阅": "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" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -394,5 +394,7 @@ | ||||||
|   "强制删除": "强制删除", |   "强制删除": "强制删除", | ||||||
|   "全部任务": "全部任务", |   "全部任务": "全部任务", | ||||||
|   "关联订阅": "关联订阅", |   "关联订阅": "关联订阅", | ||||||
|   "订阅": "订阅" |   "订阅": "订阅", | ||||||
|  |   "创建": "创建", | ||||||
|  |   "同时删除关联任务和脚本": "同时删除关联任务和脚本" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -106,7 +106,7 @@ const Dependence = () => { | ||||||
|     { |     { | ||||||
|       title: intl.get('状态'), |       title: intl.get('状态'), | ||||||
|       key: 'status', |       key: 'status', | ||||||
|       width: 100, |       width: 120, | ||||||
|       dataIndex: 'status', |       dataIndex: 'status', | ||||||
|       render: (text: string, record: any, index: number) => { |       render: (text: string, record: any, index: number) => { | ||||||
|         return ( |         return ( | ||||||
|  |  | ||||||
|  | @ -195,7 +195,7 @@ const EditModal = ({ | ||||||
|           > |           > | ||||||
|             {intl.get('清空日志')} |             {intl.get('清空日志')} | ||||||
|           </Button> |           </Button> | ||||||
|           <Button |           {/* <Button | ||||||
|             type="primary" |             type="primary" | ||||||
|             style={{ marginRight: 8 }} |             style={{ marginRight: 8 }} | ||||||
|             onClick={() => { |             onClick={() => { | ||||||
|  | @ -203,7 +203,7 @@ const EditModal = ({ | ||||||
|             }} |             }} | ||||||
|           > |           > | ||||||
|             {intl.get('设置')} |             {intl.get('设置')} | ||||||
|           </Button> |           </Button> */} | ||||||
|           <Button |           <Button | ||||||
|             type="primary" |             type="primary" | ||||||
|             style={{ marginRight: 8 }} |             style={{ marginRight: 8 }} | ||||||
|  |  | ||||||
|  | @ -12,6 +12,7 @@ import { | ||||||
|   Typography, |   Typography, | ||||||
|   Input, |   Input, | ||||||
|   Tooltip, |   Tooltip, | ||||||
|  |   Checkbox, | ||||||
| } from 'antd'; | } from 'antd'; | ||||||
| import { | import { | ||||||
|   ClockCircleOutlined, |   ClockCircleOutlined, | ||||||
|  | @ -240,6 +241,7 @@ const Subscription = () => { | ||||||
|   const [logSubscription, setLogSubscription] = useState<any>(); |   const [logSubscription, setLogSubscription] = useState<any>(); | ||||||
|   const tableRef = useRef<HTMLDivElement>(null); |   const tableRef = useRef<HTMLDivElement>(null); | ||||||
|   const tableScrollHeight = useTableScrollHeight(tableRef); |   const tableScrollHeight = useTableScrollHeight(tableRef); | ||||||
|  |   const deleteCheckRef = useRef(false); | ||||||
| 
 | 
 | ||||||
|   const runSubscription = (record: any, index: number) => { |   const runSubscription = (record: any, index: number) => { | ||||||
|     Modal.confirm({ |     Modal.confirm({ | ||||||
|  | @ -335,6 +337,10 @@ const Subscription = () => { | ||||||
|     setIsModalVisible(true); |     setIsModalVisible(true); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|  |   const onCheckChange = (e) => { | ||||||
|  |     deleteCheckRef.current = e.target.checked; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|   const delSubscription = (record: any, index: number) => { |   const delSubscription = (record: any, index: number) => { | ||||||
|     Modal.confirm({ |     Modal.confirm({ | ||||||
|       title: intl.get('确认删除'), |       title: intl.get('确认删除'), | ||||||
|  | @ -345,11 +351,19 @@ const Subscription = () => { | ||||||
|             {record.name} |             {record.name} | ||||||
|           </Text>{' '} |           </Text>{' '} | ||||||
|           {intl.get('吗')} |           {intl.get('吗')} | ||||||
|  |           <div style={{ marginTop: 20 }}> | ||||||
|  |             <Checkbox onChange={onCheckChange}> | ||||||
|  |               {intl.get('同时删除关联任务和脚本')} | ||||||
|  |             </Checkbox> | ||||||
|  |           </div> | ||||||
|         </> |         </> | ||||||
|       ), |       ), | ||||||
|       onOk() { |       onOk() { | ||||||
|         request |         request | ||||||
|           .delete(`${config.apiPrefix}subscriptions`, { data: [record.id] }) |           .delete(`${config.apiPrefix}subscriptions`, { | ||||||
|  |             data: [record.id], | ||||||
|  |             params: { force: deleteCheckRef.current }, | ||||||
|  |           }) | ||||||
|           .then(({ code, data }) => { |           .then(({ code, data }) => { | ||||||
|             if (code === 200) { |             if (code === 200) { | ||||||
|               message.success('删除成功'); |               message.success('删除成功'); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 whyour
						whyour