feat: refact id column define
This commit is contained in:
@@ -155,7 +155,7 @@ async function createToken() {
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteToken(id: number) {
|
||||
async function deleteToken(id: string) {
|
||||
try {
|
||||
await api.agents.deleteToken(id)
|
||||
await loadAgents()
|
||||
@@ -230,7 +230,7 @@ onUnmounted(() => {
|
||||
<!-- 大屏表头 -->
|
||||
<div
|
||||
class="hidden sm:flex items-center gap-2 sm:gap-4 px-3 sm:px-4 py-2 border-b bg-muted/50 text-xs sm:text-sm text-muted-foreground font-medium">
|
||||
<span class="w-10 sm:w-12 shrink-0">ID</span>
|
||||
<span class="w-10 sm:w-12 shrink-0">序号</span>
|
||||
<span class="w-6 shrink-0"></span>
|
||||
<span class="w-24 sm:w-32 shrink-0">名称</span>
|
||||
<span class="w-24 sm:w-28 shrink-0">IP</span>
|
||||
@@ -246,11 +246,11 @@ onUnmounted(() => {
|
||||
{{ searchQuery ? '无匹配结果' : '暂无 Agent' }}
|
||||
</div>
|
||||
<!-- 小屏布局 -->
|
||||
<div v-for="agent in filteredAgents" :key="agent.id"
|
||||
<div v-for="(agent, index) in filteredAgents" :key="agent.id"
|
||||
class="sm:hidden p-3 hover:bg-muted/50 transition-colors">
|
||||
<div class="flex items-start justify-between mb-2">
|
||||
<div class="flex items-center gap-2 flex-1 min-w-0">
|
||||
<span class="text-xs text-muted-foreground shrink-0">#{{ agent.id }}</span>
|
||||
<span class="text-xs text-muted-foreground shrink-0">#{{ filteredAgents.length - index }}</span>
|
||||
<span class="flex items-center shrink-0" :title="isOnline(agent) ? '在线' : '离线'">
|
||||
<div v-if="isOnline(agent)"
|
||||
class="h-5 w-5 rounded-full bg-green-500/10 flex items-center justify-center">
|
||||
@@ -310,9 +310,9 @@ onUnmounted(() => {
|
||||
</div>
|
||||
</div>
|
||||
<!-- 大屏布局 -->
|
||||
<div v-for="agent in filteredAgents" :key="`desktop-${agent.id}`"
|
||||
<div v-for="(agent, index) in filteredAgents" :key="`desktop-${agent.id}`"
|
||||
class="hidden sm:flex items-center gap-2 sm:gap-4 px-3 sm:px-4 py-2 hover:bg-muted/50 transition-colors">
|
||||
<span class="w-10 sm:w-12 shrink-0 text-muted-foreground text-xs sm:text-sm">#{{ agent.id }}</span>
|
||||
<span class="w-10 sm:w-12 shrink-0 text-muted-foreground text-xs sm:text-sm">#{{ filteredAgents.length - index }}</span>
|
||||
<span class="w-6 shrink-0 flex justify-center">
|
||||
<span class="flex justify-center shrink-0" :title="isOnline(agent) ? '在线' : '离线'">
|
||||
<div v-if="isOnline(agent)"
|
||||
|
||||
@@ -21,7 +21,7 @@ const activeTab = ref('python')
|
||||
const deps = ref<Dependency[]>([])
|
||||
const loading = ref(false)
|
||||
const installing = ref(false)
|
||||
const reinstalling = ref<number | null>(null)
|
||||
const reinstalling = ref<string | null>(null)
|
||||
const reinstallingAll = ref(false)
|
||||
const installedLangs = ref<string[]>([])
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ const envVars = ref<EnvVar[]>([])
|
||||
const showDialog = ref(false)
|
||||
const editingEnv = ref<Partial<EnvVar>>({})
|
||||
const isEdit = ref(false)
|
||||
const showValues = ref<Record<number, boolean>>({})
|
||||
const showValues = ref<Record<string, boolean>>({})
|
||||
const showDeleteDialog = ref(false)
|
||||
const deleteEnvId = ref<number | null>(null)
|
||||
const deleteEnvId = ref<string | null>(null)
|
||||
|
||||
const filterName = ref('')
|
||||
const currentPage = ref(1)
|
||||
@@ -84,7 +84,7 @@ async function saveEnv() {
|
||||
} catch { toast.error('保存失败') }
|
||||
}
|
||||
|
||||
function confirmDelete(id: number) {
|
||||
function confirmDelete(id: string) {
|
||||
deleteEnvId.value = id
|
||||
showDeleteDialog.value = true
|
||||
}
|
||||
@@ -100,7 +100,7 @@ async function deleteEnv() {
|
||||
deleteEnvId.value = null
|
||||
}
|
||||
|
||||
function toggleShow(id: number) {
|
||||
function toggleShow(id: string) {
|
||||
showValues.value[id] = !showValues.value[id]
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ const { pageSize } = useSiteSettings()
|
||||
const logs = ref<TaskLog[]>([])
|
||||
const selectedLog = ref<TaskLog | null>(null)
|
||||
const filterKeyword = ref('')
|
||||
const filterTaskId = ref<number | undefined>(undefined)
|
||||
const filterTaskId = ref<string | undefined>(undefined)
|
||||
const filterStatus = ref<string | undefined>(undefined)
|
||||
const currentPage = ref(1)
|
||||
const total = ref(0)
|
||||
@@ -49,7 +49,7 @@ const showClearDialog = ref(false)
|
||||
|
||||
// 删除单条日志弹窗
|
||||
const showDeleteDialog = ref(false)
|
||||
const deleteLogId = ref<number | null>(null)
|
||||
const deleteLogId = ref<string | null>(null)
|
||||
|
||||
const wsContent = ref('')
|
||||
const isWsLoading = ref(false)
|
||||
@@ -62,7 +62,7 @@ const decompressedOutput = computed(() => {
|
||||
|
||||
async function loadLogs() {
|
||||
try {
|
||||
const params: { page: number; page_size: number; task_id?: number; task_name?: string; status?: string } = {
|
||||
const params: { page: number; page_size: number; task_id?: string; task_name?: string; status?: string } = {
|
||||
page: currentPage.value,
|
||||
page_size: pageSize.value
|
||||
}
|
||||
@@ -241,7 +241,7 @@ async function handleClearLogs() {
|
||||
}
|
||||
}
|
||||
|
||||
function confirmDeleteLog(id: number) {
|
||||
function confirmDeleteLog(id: string) {
|
||||
deleteLogId.value = id
|
||||
showDeleteDialog.value = true
|
||||
}
|
||||
@@ -291,7 +291,7 @@ onMounted(() => {
|
||||
// 从 URL 读取参数
|
||||
const taskIdParam = route.query.task_id
|
||||
if (taskIdParam) {
|
||||
filterTaskId.value = Number(taskIdParam)
|
||||
filterTaskId.value = String(taskIdParam)
|
||||
}
|
||||
const statusParam = route.query.status
|
||||
if (statusParam) {
|
||||
@@ -302,7 +302,7 @@ onMounted(() => {
|
||||
|
||||
// 监听路由变化
|
||||
watch(() => route.query, (newQuery) => {
|
||||
filterTaskId.value = newQuery.task_id ? Number(newQuery.task_id) : undefined
|
||||
filterTaskId.value = newQuery.task_id ? String(newQuery.task_id) : undefined
|
||||
filterStatus.value = newQuery.status ? String(newQuery.status) : undefined
|
||||
currentPage.value = 1
|
||||
loadLogs()
|
||||
@@ -352,7 +352,7 @@ watch(() => route.query, (newQuery) => {
|
||||
<!-- 小屏表头 -->
|
||||
<div
|
||||
class="flex sm:hidden items-center gap-2 px-3 py-2 border-b bg-muted/20 text-xs text-muted-foreground font-medium">
|
||||
<span class="w-14 shrink-0">ID</span>
|
||||
<span class="w-14 shrink-0">序号</span>
|
||||
<span class="w-10 shrink-0 text-center">类型</span>
|
||||
<span class="flex-1 min-w-0">任务名称</span>
|
||||
<span class="w-8 shrink-0 text-center">状态</span>
|
||||
@@ -362,7 +362,7 @@ watch(() => route.query, (newQuery) => {
|
||||
<!-- 大屏表头 -->
|
||||
<div
|
||||
class="hidden sm:flex items-center gap-4 px-4 h-11 border-b bg-muted/20 text-sm text-muted-foreground font-medium">
|
||||
<span class="w-16 shrink-0">ID</span>
|
||||
<span class="w-16 shrink-0">序号</span>
|
||||
<span class="w-12 shrink-0 text-center">类型</span>
|
||||
<span class="w-36 shrink-0">任务名称</span>
|
||||
<span class="flex-1 min-w-0">命令</span>
|
||||
@@ -376,13 +376,13 @@ watch(() => route.query, (newQuery) => {
|
||||
<div v-if="logs.length === 0" class="text-sm text-muted-foreground text-center py-8">
|
||||
暂无日志
|
||||
</div>
|
||||
<div v-for="log in logs" :key="log.id" :class="[
|
||||
<div v-for="(log, index) in logs" :key="log.id" :class="[
|
||||
'cursor-pointer hover:bg-muted/30 transition-colors group',
|
||||
selectedLog?.id === log.id && 'bg-accent/50'
|
||||
]" @click="selectLog(log)">
|
||||
<!-- 小屏行 -->
|
||||
<div class="flex sm:hidden items-center gap-2 px-3 py-2">
|
||||
<span class="w-14 shrink-0 text-muted-foreground text-xs">#{{ log.id }}</span>
|
||||
<span class="w-14 shrink-0 text-muted-foreground text-xs">#{{ total - (currentPage - 1) * pageSize - index }}</span>
|
||||
<span class="w-6 shrink-0 flex justify-center" :title="getTaskTypeTitle(log.task_type || 'task')">
|
||||
<GitBranch v-if="log.task_type === TASK_TYPE.REPO" class="h-3.5 w-3.5 text-primary" />
|
||||
<Terminal v-else class="h-3.5 w-3.5 text-primary" />
|
||||
@@ -424,7 +424,7 @@ watch(() => route.query, (newQuery) => {
|
||||
</div>
|
||||
<!-- 大屏行 -->
|
||||
<div class="hidden sm:flex items-center gap-4 px-4 py-2">
|
||||
<span class="w-16 shrink-0 text-muted-foreground text-sm">#{{ log.id }}</span>
|
||||
<span class="w-16 shrink-0 text-muted-foreground text-sm">#{{ total - (currentPage - 1) * pageSize - index }}</span>
|
||||
<span class="w-10 shrink-0 flex justify-center" :title="getTaskTypeTitle(log.task_type || 'task')">
|
||||
<GitBranch v-if="log.task_type === TASK_TYPE.REPO" class="h-4 w-4 text-primary" />
|
||||
<Terminal v-else class="h-4 w-4 text-primary" />
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
const { pageSize } = useSiteSettings()
|
||||
|
||||
interface LoginLog {
|
||||
id: number
|
||||
id: string
|
||||
username: string
|
||||
ip: string
|
||||
user_agent: string
|
||||
|
||||
@@ -170,7 +170,7 @@ async function save() {
|
||||
|
||||
form.value.config = JSON.stringify(configToSave)
|
||||
form.value.command = `[${repoConfig.value.source_type}] ${repoConfig.value.source_url}`
|
||||
form.value.agent_id = selectedAgentId.value === 'local' ? null : Number(selectedAgentId.value)
|
||||
form.value.agent_id = selectedAgentId.value === 'local' ? null : selectedAgentId.value
|
||||
if (props.isEdit && form.value.id) {
|
||||
await api.tasks.update(form.value.id, form.value)
|
||||
toast.success('同步任务已更新')
|
||||
|
||||
@@ -44,7 +44,7 @@ const cleanType = ref('none')
|
||||
const cleanKeep = ref(30)
|
||||
const allEnvVars = ref<EnvVar[]>([])
|
||||
const allAgents = ref<Agent[]>([])
|
||||
const selectedEnvIds = ref<number[]>([])
|
||||
const selectedEnvIds = ref<string[]>([])
|
||||
const selectedAgentId = ref<string>('local')
|
||||
const selectedTriggerType = ref<string>('cron')
|
||||
const envSearchQuery = ref('')
|
||||
@@ -256,7 +256,7 @@ watch(() => props.open, async (val) => {
|
||||
}
|
||||
// 解析环境变量
|
||||
if (props.task?.envs) {
|
||||
selectedEnvIds.value = props.task.envs.split(',').map(s => parseInt(s.trim())).filter(n => !isNaN(n))
|
||||
selectedEnvIds.value = props.task.envs.split(',').map(s => s.trim()).filter(Boolean)
|
||||
} else {
|
||||
selectedEnvIds.value = []
|
||||
}
|
||||
@@ -303,14 +303,14 @@ async function loadData() {
|
||||
} catch { /* ignore */ }
|
||||
}
|
||||
|
||||
function addEnv(id: number) {
|
||||
function addEnv(id: string) {
|
||||
if (!selectedEnvIds.value.includes(id)) {
|
||||
selectedEnvIds.value.push(id)
|
||||
}
|
||||
envSearchQuery.value = ''
|
||||
}
|
||||
|
||||
function removeEnv(id: number) {
|
||||
function removeEnv(id: string) {
|
||||
selectedEnvIds.value = selectedEnvIds.value.filter(envId => envId !== id)
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ async function save() {
|
||||
form.value.envs = selectedEnvIds.value.join(',')
|
||||
form.value.type = 'task'
|
||||
form.value.trigger_type = selectedTriggerType.value
|
||||
form.value.agent_id = selectedAgentId.value === 'local' ? null : Number(selectedAgentId.value)
|
||||
form.value.agent_id = selectedAgentId.value === 'local' ? null : selectedAgentId.value
|
||||
|
||||
// 保存语言环境配置
|
||||
form.value.languages = selectedLangs.value.map(l => ({
|
||||
|
||||
@@ -26,19 +26,19 @@ const showRepoDialog = ref(false)
|
||||
const editingTask = ref<Partial<Task>>({})
|
||||
const isEdit = ref(false)
|
||||
const showDeleteDialog = ref(false)
|
||||
const deleteTaskId = ref<number | null>(null)
|
||||
const deleteTaskId = ref<string | null>(null)
|
||||
|
||||
const filterName = ref('')
|
||||
const filterTags = ref('')
|
||||
const filterType = ref('all')
|
||||
const filterAgentId = ref<number | null>(null)
|
||||
const filterAgentId = ref<string | null>(null)
|
||||
const currentPage = ref(1)
|
||||
const total = ref(0)
|
||||
let searchTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
// 创建 agent 映射表
|
||||
const agentMap = computed(() => {
|
||||
const map: Record<number, Agent> = {}
|
||||
const map: Record<string, Agent> = {}
|
||||
agents.value.forEach(a => { map[a.id] = a })
|
||||
return map
|
||||
})
|
||||
@@ -147,7 +147,7 @@ function duplicateTask(task: Task) {
|
||||
}
|
||||
}
|
||||
|
||||
function confirmDelete(id: number) {
|
||||
function confirmDelete(id: string) {
|
||||
deleteTaskId.value = id
|
||||
showDeleteDialog.value = true
|
||||
}
|
||||
@@ -163,9 +163,9 @@ async function deleteTask() {
|
||||
deleteTaskId.value = null
|
||||
}
|
||||
|
||||
const executingTaskId = ref<number | null>(null)
|
||||
const executingTaskId = ref<string | null>(null)
|
||||
|
||||
async function runTask(id: number) {
|
||||
async function runTask(id: string) {
|
||||
executingTaskId.value = id
|
||||
toast.message('正在执行...', { id: 'executing' })
|
||||
try {
|
||||
@@ -189,8 +189,8 @@ async function toggleTask(task: Task, enabled: boolean) {
|
||||
} catch { toast.error('操作失败') }
|
||||
}
|
||||
|
||||
function viewLogs(taskId: number) {
|
||||
router.push({ path: '/history', query: { task_id: String(taskId) } })
|
||||
function viewLogs(taskId: string) {
|
||||
router.push({ path: '/history', query: { task_id: taskId } })
|
||||
}
|
||||
|
||||
function getTaskTypeTitle(type: string) {
|
||||
@@ -204,7 +204,7 @@ onMounted(async () => {
|
||||
// 从 URL 参数读取 agent_id
|
||||
const agentIdParam = route.query.agent_id
|
||||
if (agentIdParam) {
|
||||
filterAgentId.value = Number(agentIdParam)
|
||||
filterAgentId.value = String(agentIdParam)
|
||||
}
|
||||
|
||||
loadTasks()
|
||||
@@ -212,7 +212,7 @@ onMounted(async () => {
|
||||
|
||||
// 监听路由参数变化
|
||||
watch(() => route.query.agent_id, (newVal) => {
|
||||
filterAgentId.value = newVal ? Number(newVal) : null
|
||||
filterAgentId.value = newVal ? String(newVal) : null
|
||||
currentPage.value = 1
|
||||
loadTasks()
|
||||
})
|
||||
@@ -282,7 +282,7 @@ watch(() => route.query.agent_id, (newVal) => {
|
||||
<!-- 表头 -->
|
||||
<div
|
||||
class="flex flex-wrap sm:flex-nowrap items-center gap-x-2 gap-y-2 sm:gap-4 px-3 sm:px-4 py-2 sm:py-1.5 border-b bg-muted/20 text-xs sm:text-sm text-muted-foreground font-medium min-w-0 sm:min-w-[1000px]">
|
||||
<span class="w-10 sm:w-12 shrink-0 max-sm:order-1">ID</span>
|
||||
<span class="w-10 sm:w-12 shrink-0 max-sm:order-1">序号</span>
|
||||
<span class="w-8 shrink-0 text-center max-sm:order-2">类型</span>
|
||||
<span class="flex-1 min-w-0 sm:flex-none sm:w-40 md:w-48 lg:w-56 shrink-0 max-sm:order-3">名称</span>
|
||||
<span class="w-24 sm:w-32 shrink-0 hidden md:block">执行位置</span>
|
||||
@@ -300,10 +300,9 @@ watch(() => route.query.agent_id, (newVal) => {
|
||||
<div v-if="tasks.length === 0" class="text-sm text-muted-foreground text-center py-8">
|
||||
暂无任务
|
||||
</div>
|
||||
<div v-for="task in tasks" :key="task.id"
|
||||
<div v-for="(task, index) in tasks" :key="task.id"
|
||||
class="flex flex-wrap sm:flex-nowrap items-center gap-x-2 gap-y-2 sm:gap-4 px-3 sm:px-4 py-2.5 sm:py-1.5 hover:bg-muted/30 transition-colors">
|
||||
<span class="w-10 sm:w-12 shrink-0 text-muted-foreground text-xs sm:text-sm max-sm:order-1">#{{ task.id
|
||||
}}</span>
|
||||
<span class="w-10 sm:w-12 shrink-0 text-muted-foreground text-xs sm:text-sm max-sm:order-1">#{{ total - (currentPage - 1) * pageSize - index }}</span>
|
||||
<span class="w-8 shrink-0 flex justify-center max-sm:order-2" :title="getTaskTypeTitle(task.type || 'task')">
|
||||
<GitBranch v-if="task.type === TASK_TYPE.REPO" class="h-3.5 w-3.5 sm:h-4 sm:w-4 text-primary" />
|
||||
<Terminal v-else class="h-3.5 w-3.5 sm:h-4 sm:w-4 text-primary" />
|
||||
|
||||
Reference in New Issue
Block a user