|
@@ -30,12 +30,12 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
- <el-table :data="rows.items" border stripe @selection-change="selected = $event">
|
|
|
|
|
|
|
+ <el-table :data="rows.items" border stripe @selection-change="selected = $event" @sort-change="handleSortChange">
|
|
|
<el-table-column type="selection" width="46" />
|
|
<el-table-column type="selection" width="46" />
|
|
|
- <el-table-column prop="name" label="名称" min-width="170" />
|
|
|
|
|
- <el-table-column v-if="type === 'service'" prop="display_name" label="显示名称" min-width="180" />
|
|
|
|
|
- <el-table-column prop="status" label="运行状态" width="120" />
|
|
|
|
|
- <el-table-column label="确认状态" width="120">
|
|
|
|
|
|
|
+ <el-table-column prop="name" label="名称" min-width="170" sortable="custom" />
|
|
|
|
|
+ <el-table-column v-if="type === 'service'" prop="display_name" label="显示名称" min-width="180" sortable="custom" />
|
|
|
|
|
+ <el-table-column prop="status" label="运行状态" width="120" sortable="custom" />
|
|
|
|
|
+ <el-table-column prop="confirm_status" label="确认状态" width="120" sortable="custom">
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
<el-tag :type="statusMeta(row.confirm_status).type">{{ statusMeta(row.confirm_status).label }}</el-tag>
|
|
<el-tag :type="statusMeta(row.confirm_status).type">{{ statusMeta(row.confirm_status).label }}</el-tag>
|
|
|
</template>
|
|
</template>
|
|
@@ -53,35 +53,42 @@
|
|
|
<span v-if="!row.tags?.length" class="muted">未设置</span>
|
|
<span v-if="!row.tags?.length" class="muted">未设置</span>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
- <el-table-column label="出现" width="100">
|
|
|
|
|
|
|
+ <el-table-column prop="is_present_now" label="出现" width="100" sortable="custom">
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
<el-tag :type="row.is_present_now ? 'success' : 'info'">{{ row.is_present_now ? '本次出现' : '未出现' }}</el-tag>
|
|
<el-tag :type="row.is_present_now ? 'success' : 'info'">{{ row.is_present_now ? '本次出现' : '未出现' }}</el-tag>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
- <el-table-column label="路径/命令行" min-width="260">
|
|
|
|
|
|
|
+ <el-table-column :prop="type === 'service' ? 'binary_path' : 'exe_path'" label="路径/命令行" min-width="260" sortable="custom">
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
<div class="path">{{ row.binary_path || row.exe_path || row.cmdline || '-' }}</div>
|
|
<div class="path">{{ row.binary_path || row.exe_path || row.cmdline || '-' }}</div>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
- <el-table-column prop="last_seen_at" label="最后出现" min-width="170" />
|
|
|
|
|
- <el-table-column label="操作" width="420" fixed="right">
|
|
|
|
|
|
|
+ <el-table-column v-if="type === 'service'" prop="start_type" label="启动类型" width="110" sortable="custom" />
|
|
|
|
|
+ <el-table-column v-if="type === 'process'" prop="last_pid" label="PID" width="90" sortable="custom" />
|
|
|
|
|
+ <el-table-column prop="last_seen_at" label="最后出现" min-width="170" sortable="custom" />
|
|
|
|
|
+ <el-table-column label="操作" width="360" fixed="right">
|
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
|
- <el-button size="small" @click="showDetail(row)">详情</el-button>
|
|
|
|
|
- <el-button size="small" @click="openTags(row)">标签</el-button>
|
|
|
|
|
- <el-button size="small" type="success" @click="singleUpdate(row, 'TRUSTED')">可信</el-button>
|
|
|
|
|
- <el-button size="small" type="danger" @click="singleUpdate(row, 'SUSPICIOUS')">可疑</el-button>
|
|
|
|
|
- <el-button size="small" @click="singleUpdate(row, 'IGNORED')">忽略</el-button>
|
|
|
|
|
- <template v-if="row.can_control">
|
|
|
|
|
- <template v-if="type === 'service' && row.is_present_now">
|
|
|
|
|
- <el-button size="small" type="primary" @click="control(row, 'start')">启动</el-button>
|
|
|
|
|
- <el-button size="small" type="warning" @click="control(row, 'stop')">停止</el-button>
|
|
|
|
|
- <el-button size="small" type="primary" @click="control(row, 'restart')">重启</el-button>
|
|
|
|
|
- </template>
|
|
|
|
|
- <template v-if="type === 'process'">
|
|
|
|
|
- <el-button size="small" type="primary" @click="control(row, 'start')">启动</el-button>
|
|
|
|
|
- <el-button v-if="row.is_present_now" size="small" type="warning" @click="control(row, 'stop')">停止</el-button>
|
|
|
|
|
- </template>
|
|
|
|
|
- </template>
|
|
|
|
|
|
|
+ <div class="row-actions">
|
|
|
|
|
+ <el-button size="small" @click="showDetail(row)">详情</el-button>
|
|
|
|
|
+ <el-button size="small" @click="openTags(row)">标签</el-button>
|
|
|
|
|
+ <el-button size="small" type="success" @click="singleUpdate(row, 'TRUSTED')">可信</el-button>
|
|
|
|
|
+ <el-button size="small" type="danger" @click="singleUpdate(row, 'SUSPICIOUS')">可疑</el-button>
|
|
|
|
|
+ <el-button size="small" @click="singleUpdate(row, 'IGNORED')">忽略</el-button>
|
|
|
|
|
+ <el-dropdown v-if="controlActions(row).length" trigger="click" @command="control(row, $event)">
|
|
|
|
|
+ <el-button size="small">更多</el-button>
|
|
|
|
|
+ <template #dropdown>
|
|
|
|
|
+ <el-dropdown-menu>
|
|
|
|
|
+ <el-dropdown-item
|
|
|
|
|
+ v-for="action in controlActions(row)"
|
|
|
|
|
+ :key="action.command"
|
|
|
|
|
+ :command="action.command"
|
|
|
|
|
+ >
|
|
|
|
|
+ {{ action.label }}
|
|
|
|
|
+ </el-dropdown-item>
|
|
|
|
|
+ </el-dropdown-menu>
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-dropdown>
|
|
|
|
|
+ </div>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
</el-table>
|
|
</el-table>
|
|
@@ -178,16 +185,32 @@ const query = reactive({
|
|
|
keyword: '',
|
|
keyword: '',
|
|
|
confirm_status: props.confirmStatus || '',
|
|
confirm_status: props.confirmStatus || '',
|
|
|
present: null,
|
|
present: null,
|
|
|
|
|
+ sort_by: '',
|
|
|
|
|
+ sort_order: '',
|
|
|
page: 1,
|
|
page: 1,
|
|
|
page_size: 20,
|
|
page_size: 20,
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
async function load() {
|
|
async function load() {
|
|
|
query.confirm_status = props.confirmStatus || query.confirm_status
|
|
query.confirm_status = props.confirmStatus || query.confirm_status
|
|
|
- const { data } = await api.get(basePath, { params: query })
|
|
|
|
|
|
|
+ const params = cleanParams(query)
|
|
|
|
|
+ const { data } = await api.get(basePath, { params })
|
|
|
rows.value = data
|
|
rows.value = data
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+async function handleSortChange({ prop, order }) {
|
|
|
|
|
+ query.sort_by = order ? prop : ''
|
|
|
|
|
+ query.sort_order = order === 'ascending' ? 'asc' : order === 'descending' ? 'desc' : ''
|
|
|
|
|
+ query.page = 1
|
|
|
|
|
+ await load()
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function cleanParams(source) {
|
|
|
|
|
+ return Object.fromEntries(
|
|
|
|
|
+ Object.entries(source).filter(([, value]) => value !== '' && value !== null && value !== undefined),
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
async function loadTags() {
|
|
async function loadTags() {
|
|
|
const { data } = await api.get('/api/tags')
|
|
const { data } = await api.get('/api/tags')
|
|
|
allTags.value = data.items
|
|
allTags.value = data.items
|
|
@@ -269,6 +292,23 @@ async function importAi() {
|
|
|
await load()
|
|
await load()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+function controlActions(row) {
|
|
|
|
|
+ if (!row.can_control) return []
|
|
|
|
|
+ if (props.type === 'service' && row.is_present_now) {
|
|
|
|
|
+ return [
|
|
|
|
|
+ { command: 'start', label: '启动服务' },
|
|
|
|
|
+ { command: 'stop', label: '停止服务' },
|
|
|
|
|
+ { command: 'restart', label: '重新启动服务' },
|
|
|
|
|
+ ]
|
|
|
|
|
+ }
|
|
|
|
|
+ if (props.type === 'process') {
|
|
|
|
|
+ const actions = [{ command: 'start', label: '启动进程' }]
|
|
|
|
|
+ if (row.is_present_now) actions.push({ command: 'stop', label: '停止进程' })
|
|
|
|
|
+ return actions
|
|
|
|
|
+ }
|
|
|
|
|
+ return []
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
async function control(row, action) {
|
|
async function control(row, action) {
|
|
|
const actionLabel = { start: '启动', stop: '停止', restart: '重启' }[action]
|
|
const actionLabel = { start: '启动', stop: '停止', restart: '重启' }[action]
|
|
|
await ElMessageBox.confirm(`确认${actionLabel}“${row.name}”?`, `${actionLabel}确认`, { type: 'warning' })
|
|
await ElMessageBox.confirm(`确认${actionLabel}“${row.name}”?`, `${actionLabel}确认`, { type: 'warning' })
|