依赖管理增加直接强制删除

This commit is contained in:
whyour 2022-04-23 15:02:54 +08:00
parent 5be421b4ea
commit 1b893f35ba
5 changed files with 66 additions and 35 deletions

View File

@ -94,7 +94,7 @@ export default (app: Router) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
const dependenceService = Container.get(DependenceService); const dependenceService = Container.get(DependenceService);
const data = await dependenceService.removeDb(req.body); const data = await dependenceService.remove(req.body, true);
return res.send({ code: 200, data }); return res.send({ code: 200, data });
} catch (e) { } catch (e) {
logger.error('🔥 error: %o', e); logger.error('🔥 error: %o', e);

View File

@ -37,13 +37,13 @@ export enum DependenceTypes {
} }
export enum InstallDependenceCommandTypes { export enum InstallDependenceCommandTypes {
'npm i -g --force', 'npm i -g -f --loglevel warn',
'pip3 install', 'pip3 install',
'apk add --no-cache -f', 'apk add --no-cache -f',
} }
export enum unInstallDependenceCommandTypes { export enum unInstallDependenceCommandTypes {
'npm uninstall -g --force', 'npm uninstall -g -f --loglevel warn',
'pip3 uninstall -y', 'pip3 uninstall -y',
'apk del -f', 'apk del -f',
} }

View File

@ -13,5 +13,6 @@ export class SockMessage {
export type SockMessageType = export type SockMessageType =
| 'ping' | 'ping'
| 'installDependence' | 'installDependence'
| 'uninstallDependence'
| 'updateSystemVersion' | 'updateSystemVersion'
| 'manuallyRunScript'; | 'manuallyRunScript';

View File

@ -56,13 +56,13 @@ export default class DependenceService {
return await this.getDb({ id: payload.id }); return await this.getDb({ id: payload.id });
} }
public async remove(ids: number[]) { public async remove(ids: number[], force = false): Promise<Dependence[]> {
await DependenceModel.update( await DependenceModel.update(
{ status: DependenceStatus.removing, log: [] }, { status: DependenceStatus.removing, log: [] },
{ where: { id: ids } }, { where: { id: ids } },
); );
const docs = await DependenceModel.findAll({ where: { id: ids } }); const docs = await DependenceModel.findAll({ where: { id: ids } });
this.installOrUninstallDependencies(docs, false); this.installOrUninstallDependencies(docs, false, force);
return docs; return docs;
} }
@ -128,12 +128,16 @@ export default class DependenceService {
public installOrUninstallDependencies( public installOrUninstallDependencies(
dependencies: Dependence[], dependencies: Dependence[],
isInstall: boolean = true, isInstall: boolean = true,
force: boolean = false,
) { ) {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {
if (dependencies.length === 0) { if (dependencies.length === 0) {
resolve(null); resolve(null);
return; return;
} }
const socketMessageType = !force
? 'installDependence'
: 'uninstallDependence';
const depNames = dependencies.map((x) => x.name).join(' '); const depNames = dependencies.map((x) => x.name).join(' ');
const depRunCommand = ( const depRunCommand = (
isInstall isInstall
@ -145,21 +149,21 @@ export default class DependenceService {
const cp = spawn(`${depRunCommand} ${depNames}`, { shell: '/bin/bash' }); const cp = spawn(`${depRunCommand} ${depNames}`, { shell: '/bin/bash' });
const startTime = Date.now(); const startTime = Date.now();
this.sockService.sendMessage({ this.sockService.sendMessage({
type: 'installDependence', type: socketMessageType,
message: `开始${actionText}依赖 ${depNames},开始时间 ${new Date( message: `开始${actionText}依赖 ${depNames},开始时间 ${new Date(
startTime, startTime,
).toLocaleString()}`, ).toLocaleString()}\n\n`,
references: depIds, references: depIds,
}); });
await this.updateLog( await this.updateLog(
depIds, depIds,
`开始${actionText}依赖 ${depNames},开始时间 ${new Date( `开始${actionText}依赖 ${depNames},开始时间 ${new Date(
startTime, startTime,
).toLocaleString()}\n`, ).toLocaleString()}\n\n`,
); );
cp.stdout.on('data', async (data) => { cp.stdout.on('data', async (data) => {
this.sockService.sendMessage({ this.sockService.sendMessage({
type: 'installDependence', type: socketMessageType,
message: data.toString(), message: data.toString(),
references: depIds, references: depIds,
}); });
@ -168,7 +172,7 @@ export default class DependenceService {
cp.stderr.on('data', async (data) => { cp.stderr.on('data', async (data) => {
this.sockService.sendMessage({ this.sockService.sendMessage({
type: 'installDependence', type: socketMessageType,
message: data.toString(), message: data.toString(),
references: depIds, references: depIds,
}); });
@ -177,7 +181,7 @@ export default class DependenceService {
cp.on('error', async (err) => { cp.on('error', async (err) => {
this.sockService.sendMessage({ this.sockService.sendMessage({
type: 'installDependence', type: socketMessageType,
message: JSON.stringify(err), message: JSON.stringify(err),
references: depIds, references: depIds,
}); });
@ -191,15 +195,15 @@ export default class DependenceService {
const resultText = isSucceed ? '成功' : '失败'; const resultText = isSucceed ? '成功' : '失败';
this.sockService.sendMessage({ this.sockService.sendMessage({
type: 'installDependence', type: socketMessageType,
message: `依赖${actionText}${resultText},结束时间 ${new Date( message: `\n依赖${actionText}${resultText},结束时间 ${new Date(
endTime, endTime,
).toLocaleString()} ${(endTime - startTime) / 1000} `, ).toLocaleString()} ${(endTime - startTime) / 1000} `,
references: depIds, references: depIds,
}); });
await this.updateLog( await this.updateLog(
depIds, depIds,
`依赖${actionText}${resultText},结束时间 ${new Date( `\n依赖${actionText}${resultText},结束时间 ${new Date(
endTime, endTime,
).toLocaleString()} ${(endTime - startTime) / 1000} `, ).toLocaleString()} ${(endTime - startTime) / 1000} `,
); );
@ -216,11 +220,9 @@ export default class DependenceService {
} }
await DependenceModel.update({ status }, { where: { id: depIds } }); await DependenceModel.update({ status }, { where: { id: depIds } });
// 如果删除依赖成功3秒后删除数据库记录 // 如果删除依赖成功或者强制删除
if (isSucceed && !isInstall) { if ((isSucceed || force) && !isInstall) {
setTimeout(() => { this.removeDb(depIds);
this.removeDb(depIds);
}, 5000);
} }
resolve(null); resolve(null);

View File

@ -16,7 +16,7 @@ import {
DeleteOutlined, DeleteOutlined,
SyncOutlined, SyncOutlined,
CheckCircleOutlined, CheckCircleOutlined,
StopOutlined, DeleteFilled,
BugOutlined, BugOutlined,
FileTextOutlined, FileTextOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
@ -120,6 +120,15 @@ const Dependence = ({ headerStyle, isPhone, socketMessage }: any) => {
const isPc = !isPhone; const isPc = !isPhone;
return ( return (
<Space size="middle"> <Space size="middle">
<Tooltip title={isPc ? '日志' : ''}>
<a
onClick={() => {
setLogDependence({ ...record, timestamp: Date.now() });
}}
>
<FileTextOutlined />
</a>
</Tooltip>
{record.status !== Status. && {record.status !== Status. &&
record.status !== Status. && ( record.status !== Status. && (
<> <>
@ -133,17 +142,13 @@ const Dependence = ({ headerStyle, isPhone, socketMessage }: any) => {
<DeleteOutlined /> <DeleteOutlined />
</a> </a>
</Tooltip> </Tooltip>
<Tooltip title={isPc ? '强制删除' : ''}>
<a onClick={() => deleteDependence(record, index, true)}>
<DeleteFilled />
</a>
</Tooltip>
</> </>
)} )}
<Tooltip title={isPc ? '日志' : ''}>
<a
onClick={() => {
setLogDependence({ ...record, timestamp: Date.now() });
}}
>
<FileTextOutlined />
</a>
</Tooltip>
</Space> </Space>
); );
}, },
@ -182,7 +187,11 @@ const Dependence = ({ headerStyle, isPhone, socketMessage }: any) => {
setIsModalVisible(true); setIsModalVisible(true);
}; };
const deleteDependence = (record: any, index: number) => { const deleteDependence = (
record: any,
index: number,
force: boolean = false,
) => {
Modal.confirm({ Modal.confirm({
title: '确认删除', title: '确认删除',
content: ( content: (
@ -196,10 +205,19 @@ const Dependence = ({ headerStyle, isPhone, socketMessage }: any) => {
), ),
onOk() { onOk() {
request request
.delete(`${config.apiPrefix}dependencies`, { data: [record.id] }) .delete(`${config.apiPrefix}dependencies${force ? '/force' : ''}`, {
data: [record.id],
})
.then((data: any) => { .then((data: any) => {
if (data.code === 200) { if (data.code === 200) {
handleDependence(data.data[0]); if (force) {
const i = value.findIndex((x) => x.id === data.data[0].id);
if (i !== -1) {
const result = [...value];
result.splice(i, 1);
setValue(result);
}
}
} else { } else {
message.error(data); message.error(data);
} }
@ -275,13 +293,16 @@ const Dependence = ({ headerStyle, isPhone, socketMessage }: any) => {
onChange: onSelectChange, onChange: onSelectChange,
}; };
const delDependencies = () => { const delDependencies = (force: boolean) => {
const forceUrl = force ? '/force' : '';
Modal.confirm({ Modal.confirm({
title: '确认删除', title: '确认删除',
content: <></>, content: <></>,
onOk() { onOk() {
request request
.delete(`${config.apiPrefix}dependencies`, { data: selectedRowIds }) .delete(`${config.apiPrefix}dependencies${forceUrl}`, {
data: selectedRowIds,
})
.then((data: any) => { .then((data: any) => {
if (data.code === 200) { if (data.code === 200) {
setSelectedRowIds([]); setSelectedRowIds([]);
@ -377,10 +398,17 @@ const Dependence = ({ headerStyle, isPhone, socketMessage }: any) => {
<Button <Button
type="primary" type="primary"
style={{ marginBottom: 5, marginLeft: 8 }} style={{ marginBottom: 5, marginLeft: 8 }}
onClick={delDependencies} onClick={() => delDependencies(false)}
> >
</Button> </Button>
<Button
type="primary"
style={{ marginBottom: 5, marginLeft: 8 }}
onClick={() => delDependencies(true)}
>
</Button>
<span style={{ marginLeft: 8 }}> <span style={{ marginLeft: 8 }}>
<a>{selectedRowIds?.length}</a> <a>{selectedRowIds?.length}</a>