优化: 前端DRY收敛与命名对齐
审批等待格式化与阈值沉 utils/time 正典 相对时间阶梯三套收敛 formatRelative 参数化 灵感状态表沉 constants,透传通道退役 aggText/clearOwn 等命名对齐,IPC 参数名统一 conversation_id
This commit is contained in:
@@ -52,7 +52,7 @@ import { ref, computed, watch, nextTick, onMounted, onBeforeUnmount } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import ToolCard from './ToolCard.vue'
|
||||
import { listen, type UnlistenFn } from '@tauri-apps/api/event'
|
||||
import { aggregateCalls, aggText } from '@/composables/ai/useTurnTrace'
|
||||
import { aggregateCalls, turnSummaryText } from '@/composables/ai/useTurnTrace'
|
||||
import type { AiToolCallInfo } from '@/api/types'
|
||||
|
||||
// useI18n needed for $t() in template (collapseAll / expandAll) + groupDisplayName(i18n key)
|
||||
@@ -230,7 +230,7 @@ function groupDisplayName(group: ToolCallGroup): string {
|
||||
|
||||
/** 分组聚合行文案:「N 次调用 · 成功 x 失败 y」(零值项省略;与单卡状态点同源 isToolFailure 判定) */
|
||||
function groupAggText(group: ToolCallGroup): string {
|
||||
return aggText(aggregateCalls(group.calls))
|
||||
return turnSummaryText(aggregateCalls(group.calls))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,7 @@ import { useMarkdown } from '../../composables/useMarkdown'
|
||||
import { useMessageScroll } from '../../composables/ai/useMessageScroll'
|
||||
import { useStreamRenderer } from '../../composables/ai/useStreamRenderer'
|
||||
import { loadMoreHistory, getLoadMoreState } from '../../composables/ai/useAiConversations'
|
||||
import { collectTurnStats, aggText, type TurnCallStats } from '../../composables/ai/useTurnTrace'
|
||||
import { collectTurnStats, turnSummaryText, type TurnCallStats } from '../../composables/ai/useTurnTrace'
|
||||
import ToolCardList from '../ToolCardList.vue'
|
||||
import MessageItem from './MessageItem.vue'
|
||||
import EmptyState from './EmptyState.vue'
|
||||
@@ -741,9 +741,9 @@ function toggleTrace(key: string): void {
|
||||
expandedTraceIds.value = next
|
||||
}
|
||||
|
||||
/** 轨迹卡聚合行:「N 次调用 · 成功 x 失败 y · 总耗时 T」(拼装统一走 useTurnTrace.aggText) */
|
||||
/** 轨迹卡聚合行:「N 次调用 · 成功 x 失败 y · 总耗时 T」(拼装统一走 useTurnTrace.turnSummaryText) */
|
||||
function traceAggText(stats: TurnCallStats, startTs: number, endTs: number): string {
|
||||
return aggText(stats, endTs - startTs)
|
||||
return turnSummaryText(stats, endTs - startTs)
|
||||
}
|
||||
|
||||
/** 轨迹卡 hover:绝对起止时刻(相对时长之外可溯源具体时间) */
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
>
|
||||
🚀 {{ $t('ideas.promotedProject') }} →
|
||||
</router-link>
|
||||
<span class="status-tag" :class="'status-' + idea.status">{{ $t(statusLabelKey(idea.status)) }}</span>
|
||||
<span class="status-tag" :class="'status-' + idea.status">{{ $t(ideaStatusLabelKey(idea.status)) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- B-260615-25:灵感描述 Markdown 渲染,复用 useMarkdown composable(同 B-24 TaskDetail),空值回退 — -->
|
||||
@@ -268,7 +268,7 @@
|
||||
:class="'status-' + idea.status"
|
||||
@click="statusMenuOpen = !statusMenuOpen"
|
||||
>
|
||||
{{ $t(statusLabelKey(idea.status)) }}
|
||||
{{ $t(ideaStatusLabelKey(idea.status)) }}
|
||||
<span class="status-caret" :class="{ 'is-open': statusMenuOpen }">▾</span>
|
||||
</button>
|
||||
<ul v-show="statusMenuOpen" class="status-menu">
|
||||
@@ -306,6 +306,7 @@ import { useRendered } from '../../composables/useMarkdown'
|
||||
import { ideaApi } from '../../api'
|
||||
import { formatDate } from '../../utils/time'
|
||||
import { parseScores, assessmentClass, assessmentLabel, scoreTier } from '../../utils/ideaEval'
|
||||
import { IDEA_STATUS_OPTIONS, ideaStatusLabelKey } from '../../constants/project'
|
||||
import type { IdeaRecord, IdeaStatus, IdeaEvaluationRecord } from '../../api/types'
|
||||
|
||||
const props = defineProps<{
|
||||
@@ -314,7 +315,6 @@ const props = defineProps<{
|
||||
evalError: string
|
||||
promoting: boolean
|
||||
deleting: boolean
|
||||
statusOptions: { value: IdeaStatus; labelKey: string }[]
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -390,11 +390,11 @@ watch(() => props.idea.id, () => {
|
||||
watch(() => props.idea.description, () => void nextTick(measureDesc))
|
||||
|
||||
// P1-④ 状态切换 select → badge 点击:点击当前 badge 展开/收起下拉菜单,
|
||||
// 选中项后 emit('status-change') 交父组件确认+落库(沿用既有契约,不破坏 statusOptions 来源)。
|
||||
// 选中项后 emit('status-change') 交父组件确认+落库(沿用既有契约)。
|
||||
const statusMenuOpen = ref(false)
|
||||
// 状态下拉排除 promoted(立项走独立 promoteToProject 流程,列表状态菜单同排除,
|
||||
// 见 Ideas.vue onStatusChange 兜底);statusOptions 仍含 promoted 供 label 映射(已转立项的灵感 badge 正常显示)。
|
||||
const menuStatusOptions = computed(() => props.statusOptions.filter(s => s.value !== 'promoted'))
|
||||
// 见 Ideas.vue onStatusChange 兜底);状态表(含 promoted 供 badge label 映射)单一数据源在 @/constants/project。
|
||||
const menuStatusOptions = computed(() => IDEA_STATUS_OPTIONS.filter(s => s.value !== 'promoted'))
|
||||
function closeStatusMenu() {
|
||||
statusMenuOpen.value = false
|
||||
}
|
||||
@@ -515,10 +515,7 @@ function cancelTagsEdit() {
|
||||
tagsEditing.value = false
|
||||
}
|
||||
|
||||
// 任意 status 字符串 → 对应 i18n key;未知状态回退到原值显示
|
||||
function statusLabelKey(status: IdeaStatus): string {
|
||||
return props.statusOptions.find(s => s.value === status)?.labelKey ?? status
|
||||
}
|
||||
// 任意 status → i18n key 的映射走 @/constants/project ideaStatusLabelKey(与列表同源)
|
||||
|
||||
// 灵感描述 Markdown 渲染(复用 AiChat/TaskDetail 同款渲染器,模块级单例),
|
||||
// useRendered 封装 computed(读 mdReady 触发响应式 + renderMd)+ ensureLoaded(幂等预热)
|
||||
|
||||
@@ -147,6 +147,7 @@ import {
|
||||
knowledgeConfidenceLabel as confidenceLabel,
|
||||
} from '@/stores/knowledge'
|
||||
import { useRendered } from '@/composables/useMarkdown'
|
||||
import { formatRelative } from '@/utils/time'
|
||||
import type { KnowledgeDetailPayload, KnowledgeEventRecord } from '@/api/types'
|
||||
|
||||
// 详情面板子组件(Knowledge.vue 拆分,SW-260618-20):
|
||||
@@ -317,20 +318,12 @@ const timelineNodes = computed(() => {
|
||||
return nodes
|
||||
})
|
||||
|
||||
// ===== 标签/时间辅助(kind*/status/confidence label 由 @/stores/knowledge 共用,相对时间本组件自留 30 天截止)=====
|
||||
// 相对时间:复用 common.* 既有 key(justNow/minutesAgo/hoursAgo/dayAgo),30 天以上回退绝对值
|
||||
// ===== 标签/时间辅助(kind*/status/confidence label 由 @/stores/knowledge 共用)=====
|
||||
// 相对时间:走 @/utils/time formatRelative(30 天以上回退绝对日期,档位与全局同源)
|
||||
function relativeTime(millisStr: string): string {
|
||||
const ms = Number(millisStr)
|
||||
if (!ms) return ''
|
||||
const diff = Date.now() - ms
|
||||
const min = Math.floor(diff / 60000)
|
||||
if (min < 1) return t('common.justNow')
|
||||
if (min < 60) return t('common.minutesAgo', { n: min })
|
||||
const hr = Math.floor(min / 60)
|
||||
if (hr < 24) return t('common.hoursAgo', { n: hr })
|
||||
const day = Math.floor(hr / 24)
|
||||
if (day < 30) return t('common.dayAgo', { n: day })
|
||||
return t('common.ago', { time: new Date(ms).toLocaleDateString() })
|
||||
return formatRelative(ms, { absAfterDays: 30 })
|
||||
}
|
||||
|
||||
// 切换知识时重置引用列表「加载更多」上限 + 折叠态(对齐原 Knowledge.vue selectKnowledge 内 refLimit=10 行为)
|
||||
|
||||
@@ -165,6 +165,7 @@
|
||||
*/
|
||||
import { ref, computed, watch } from 'vue'
|
||||
import { moduleApi, type GitStatusResult } from '@/api/module'
|
||||
import { formatRelative } from '@/utils/time'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
@@ -274,19 +275,10 @@ function statusLabel(s: string): string {
|
||||
return x.charAt(0) || '?'
|
||||
}
|
||||
|
||||
/** 格式化 Unix 时间戳为相对时间或具体时间 */
|
||||
/** 格式化 Unix 时间戳为相对时间或具体时间(阶梯走 @/utils/time formatRelative:昨天档 + 30 天截断 ISO 日期) */
|
||||
function formatTime(ts: number): string {
|
||||
if (!ts) return ''
|
||||
const now = Math.floor(Date.now() / 1000)
|
||||
const diffSec = now - ts
|
||||
if (diffSec < 60) return t('common.justNow')
|
||||
if (diffSec < 3600) return t('common.minutesAgo', { n: Math.floor(diffSec / 60) })
|
||||
if (diffSec < 86400) return t('common.hoursAgo', { n: Math.floor(diffSec / 3600) })
|
||||
if (diffSec < 172800) return t('common.yesterday')
|
||||
if (diffSec < 2592000) return t('common.dayAgo', { n: Math.floor(diffSec / 86400) })
|
||||
// 超过 30 天显示具体日期
|
||||
const d = new Date(ts * 1000)
|
||||
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
|
||||
return formatRelative(ts, { yesterday: true, absAfterDays: 30, absStyle: 'iso' })
|
||||
}
|
||||
|
||||
/** 计算文件路径的目录深度(用于缩进)。root 级文件返回 0。 */
|
||||
|
||||
Reference in New Issue
Block a user