90 lines
2.5 KiB
Vue
90 lines
2.5 KiB
Vue
<template>
|
||
<div
|
||
class="w-full h-full overflow-auto p-3 rounded-lg cursor-pointer"
|
||
:class="stateClass"
|
||
@click="$emit('update-state', { nodeId: id, state: nextState })"
|
||
>
|
||
<div v-if="data.frontmatter?.alarm" class="text-xs text-yellow-400 mb-1 flex items-center gap-1">
|
||
<span>⏰</span>
|
||
<span>{{ formatAlarm(data.frontmatter.alarm) }}</span>
|
||
</div>
|
||
|
||
<div v-if="data.frontmatter?.assigned_to" class="text-xs text-slate-400 mb-1">
|
||
👤 {{ data.frontmatter.assigned_to }}
|
||
</div>
|
||
|
||
<div v-if="data.text" class="prose prose-invert prose-sm max-w-none" v-html="renderedHtml" />
|
||
|
||
<div v-else-if="data.file" class="text-sm text-blue-400">
|
||
📄 {{ data.file }}
|
||
</div>
|
||
|
||
<div class="mt-2 flex items-center gap-2">
|
||
<span
|
||
class="text-xs px-2 py-0.5 rounded-full"
|
||
:class="badgeClass"
|
||
>
|
||
{{ stateLabel }}
|
||
</span>
|
||
<span v-if="data.frontmatter?.script_id" class="text-xs text-purple-400">
|
||
⚡ {{ data.frontmatter.script_id }}
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup>
|
||
const props = defineProps({
|
||
id: { type: String, required: true },
|
||
data: { type: Object, required: true },
|
||
isFile: { type: Boolean, default: false }
|
||
})
|
||
|
||
const emit = defineEmits(['update-state'])
|
||
|
||
const { renderMarkdown } = useCanvas()
|
||
|
||
const renderedHtml = computed(() => {
|
||
return renderMarkdown(props.data.text || '')
|
||
})
|
||
|
||
const currentState = computed(() => props.data.state || 'pending')
|
||
|
||
const nextState = computed(() => {
|
||
const s = currentState.value
|
||
return s === 'pending' ? 'in_progress' : s === 'in_progress' ? 'completed' : 'pending'
|
||
})
|
||
|
||
const stateClass = computed(() => {
|
||
switch (currentState.value) {
|
||
case 'completed': return 'bg-emerald-900/40 border-emerald-700'
|
||
case 'in_progress': return 'bg-blue-900/40 border-blue-700'
|
||
default: return 'bg-slate-800 border-slate-700'
|
||
}
|
||
})
|
||
|
||
const badgeClass = computed(() => {
|
||
switch (currentState.value) {
|
||
case 'completed': return 'bg-emerald-700 text-emerald-100'
|
||
case 'in_progress': return 'bg-blue-700 text-blue-100'
|
||
default: return 'bg-slate-700 text-slate-300'
|
||
}
|
||
})
|
||
|
||
const stateLabel = computed(() => {
|
||
switch (currentState.value) {
|
||
case 'completed': return '✅ Выполнено'
|
||
case 'in_progress': return '🔧 В работе'
|
||
default: return '📋 Ожидает'
|
||
}
|
||
})
|
||
|
||
const formatAlarm = (alarm) => {
|
||
try {
|
||
return new Date(alarm).toLocaleString('ru-RU')
|
||
} catch {
|
||
return alarm
|
||
}
|
||
}
|
||
</script>
|