Files
cultivation-world-simulator/web/src/components/layout/StatusWidget.vue
bridge d53d5885c0 feat: add active domains serialization and UI integration
- Implemented `serialize_active_domains` function to gather and format active hidden domains from the game world.
- Updated `game_loop` to include active domains in the broadcast state.
- Enhanced `StatusBar` component to display active domains with a new `StatusWidget`, including dynamic labels and colors based on the number of active domains.
- Added localization support for hidden domain messages in both English and Chinese.
- Updated the world store to manage active domains state and synchronize with the backend.
2026-02-01 12:20:27 +08:00

106 lines
3.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { NPopover, NList, NListItem, NTag, NEmpty } from 'naive-ui'
import type { HiddenDomainInfo } from '../../types/core'
interface Props {
// 触发器显示
label: string
color?: string
// 弹窗内容
title?: string
items?: HiddenDomainInfo[] // 通用列表数据 (这里暂时专用于秘境,如果未来需要其他类型再泛型化)
emptyText?: string
// 模式: 'single' (天地灵机) 或 'list' (秘境)
mode?: 'single' | 'list'
}
const props = withDefaults(defineProps<Props>(), {
color: '#ccc',
items: () => [],
mode: 'list',
emptyText: '暂无数据'
})
// 发射点击事件(用于天地灵机的"更易天象"
const emit = defineEmits(['trigger-click'])
</script>
<template>
<div class="status-widget">
<span class="divider">|</span>
<n-popover trigger="click" placement="bottom" style="max-width: 350px;">
<template #trigger>
<span
class="widget-trigger"
:style="{ color: props.color }"
@click="emit('trigger-click')"
>
{{ props.label }}
</span>
</template>
<!-- 弹窗内容区 -->
<div class="widget-content">
<!-- 模式A: 单个详情 (复用天地灵机样式) -->
<slot name="single" v-if="mode === 'single'"></slot>
<!-- 模式B: 列表展示 (用于秘境) -->
<div v-else-if="mode === 'list'" class="list-container">
<div class="list-header" v-if="title">{{ title }}</div>
<n-list v-if="items.length > 0" hoverable clickable>
<n-list-item v-for="item in items" :key="item.id">
<div class="domain-item">
<div class="d-header">
<span class="d-name">{{ item.name }}</span>
<n-tag size="small" :bordered="false" type="warning" class="d-tag">
{{ item.max_realm }}
</n-tag>
</div>
<div class="d-desc">{{ item.desc }}</div>
<div class="d-stats">
<span>💀 {{ (item.danger_prob * 100).toFixed(0) }}%</span>
<span>🎁 {{ (item.drop_prob * 100).toFixed(0) }}%</span>
</div>
</div>
</n-list-item>
</n-list>
<n-empty v-else :description="emptyText" class="empty-state" />
</div>
</div>
</n-popover>
</div>
</template>
<style scoped>
.widget-trigger {
cursor: pointer;
font-weight: bold;
transition: opacity 0.2s;
}
.widget-trigger:hover { opacity: 0.8; }
.divider { color: #444; margin-right: 10px; }
.list-header {
font-weight: bold;
padding: 8px 12px;
border-bottom: 1px solid #333;
margin-bottom: 4px;
font-size: 14px;
}
.domain-item { padding: 4px 0; }
.d-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; }
.d-name { font-weight: bold; color: #fadb14; font-size: 14px; }
.d-tag { font-size: 10px; height: 18px; line-height: 18px; }
.d-desc { font-size: 12px; color: #aaa; margin-bottom: 8px; line-height: 1.4; }
.d-stats { display: flex; gap: 12px; font-size: 12px; color: #888; }
.empty-state { padding: 20px; }
/* Naive UI List Override */
:deep(.n-list-item) {
padding: 8px 12px !important;
}
</style>