XuqmGroup-Web/tenant-platform/src/views/bug-collect/BugCollectWebhooks.vue

154 行
4.8 KiB
Vue

<template>
<div>
<div class="toolbar toolbar-space-between" style="margin-bottom: 24px">
<h2 style="margin: 0">Webhook 配置</h2>
<el-button type="primary" @click="openDialog()">新增 Webhook</el-button>
</div>
<el-card shadow="never">
<el-table :data="webhooks" v-loading="loading" border stripe>
<el-table-column prop="url" label="回调地址" min-width="300" show-overflow-tooltip />
<el-table-column label="事件类型" min-width="200">
<template #default="{ row }">
<el-tag v-for="t in row.eventTypes" :key="t" size="small" style="margin-right: 4px">{{ t }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="cooldownSeconds" label="冷却(秒)" width="110" />
<el-table-column prop="enabled" label="状态" width="90">
<template #default="{ row }">
<el-tag :type="row.enabled ? 'success' : 'info'" size="small">
{{ row.enabled ? '启用' : '停用' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="160" align="center">
<template #default="{ row }">
<el-button link type="primary" size="small" @click="openDialog(row)">编辑</el-button>
<el-popconfirm title="确认删除?" @confirm="handleDelete(row.id)">
<template #reference>
<el-button link type="danger" size="small">删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- Dialog -->
<el-dialog
v-model="dialogVisible"
:title="editingId ? '编辑 Webhook' : '新增 Webhook'"
width="520px"
destroy-on-close
>
<el-form :model="form" label-width="100px">
<el-form-item label="回调地址" required>
<el-input v-model="form.url" placeholder="https://example.com/webhook" />
</el-form-item>
<el-form-item label="事件类型" required>
<el-select v-model="form.eventTypes" multiple style="width: 100%" placeholder="选择事件类型">
<el-option label="ISSUE_NEW" value="ISSUE_NEW" />
<el-option label="ISSUE_RESOLVED" value="ISSUE_RESOLVED" />
<el-option label="CRASH_SPIKE" value="CRASH_SPIKE" />
<el-option label="ALL" value="ALL" />
</el-select>
</el-form-item>
<el-form-item label="冷却时间">
<el-input-number v-model="form.cooldownSeconds" :min="0" :max="3600" :step="60" />
<span style="margin-left: 8px; color: #999"></span>
</el-form-item>
<el-form-item label="启用">
<el-switch v-model="form.enabled" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" :loading="saving" @click="handleSave">保存</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ElMessage } from 'element-plus'
import { bugCollectApi, type BugCollectWebhook } from '@/api/bugcollect'
const webhooks = ref<BugCollectWebhook[]>([])
const loading = ref(false)
const dialogVisible = ref(false)
const saving = ref(false)
const editingId = ref('')
const form = ref({
url: '',
eventTypes: [] as string[],
cooldownSeconds: 300,
enabled: true,
})
async function loadWebhooks() {
loading.value = true
try {
const res = await bugCollectApi.webhooks.list()
webhooks.value = res.data.data
} catch {
} finally {
loading.value = false
}
}
function openDialog(row?: BugCollectWebhook) {
if (row) {
editingId.value = row.id
form.value = {
url: row.url,
eventTypes: [...row.eventTypes],
cooldownSeconds: row.cooldownSeconds,
enabled: row.enabled,
}
} else {
editingId.value = ''
form.value = { url: '', eventTypes: [], cooldownSeconds: 300, enabled: true }
}
dialogVisible.value = true
}
async function handleSave() {
if (!form.value.url || !form.value.eventTypes.length) return
saving.value = true
try {
if (editingId.value) {
await bugCollectApi.webhooks.update(editingId.value, form.value)
ElMessage.success('更新成功')
} else {
await bugCollectApi.webhooks.create(form.value)
ElMessage.success('创建成功')
}
dialogVisible.value = false
loadWebhooks()
} catch {
} finally {
saving.value = false
}
}
async function handleDelete(id: string) {
try {
await bugCollectApi.webhooks.delete(id)
ElMessage.success('删除成功')
loadWebhooks()
} catch {}
}
onMounted(loadWebhooks)
</script>
<style scoped>
.toolbar-space-between {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>