mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-04-29 16:22:43 +08:00
fix: 部分UI在英文设置下未国际化
This commit is contained in:
@@ -78,7 +78,7 @@ const monthNames = computed(() => [
|
|||||||
const typeChartData = computed<EChartPieData>(() => {
|
const typeChartData = computed<EChartPieData>(() => {
|
||||||
const sorted = [...messageTypes.value].sort((a, b) => b.count - a.count)
|
const sorted = [...messageTypes.value].sort((a, b) => b.count - a.count)
|
||||||
return {
|
return {
|
||||||
labels: sorted.map((item) => getMessageTypeName(item.type)),
|
labels: sorted.map((item) => getMessageTypeName(item.type, t)),
|
||||||
values: sorted.map((item) => item.count),
|
values: sorted.map((item) => item.count),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -89,7 +89,7 @@ const typeSummary = computed(() => {
|
|||||||
const sorted = [...messageTypes.value].sort((a, b) => b.count - a.count)
|
const sorted = [...messageTypes.value].sort((a, b) => b.count - a.count)
|
||||||
|
|
||||||
return sorted.map((item) => ({
|
return sorted.map((item) => ({
|
||||||
name: getMessageTypeName(item.type),
|
name: getMessageTypeName(item.type, t),
|
||||||
count: item.count,
|
count: item.count,
|
||||||
percentage: total > 0 ? Math.round((item.count / total) * 100) : 0,
|
percentage: total > 0 ? Math.round((item.count / total) * 100) : 0,
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -25,32 +25,42 @@ export enum MessageType {
|
|||||||
OTHER = 99,
|
OTHER = 99,
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 消息类型名称映射 */
|
/** 消息类型 i18n key 映射 */
|
||||||
const MESSAGE_TYPE_NAMES: Record<number, string> = {
|
const MESSAGE_TYPE_KEYS: Record<number, string> = {
|
||||||
[MessageType.TEXT]: '文字',
|
// 基础消息类型
|
||||||
[MessageType.IMAGE]: '图片',
|
[MessageType.TEXT]: 'text',
|
||||||
[MessageType.VOICE]: '语音',
|
[MessageType.IMAGE]: 'image',
|
||||||
[MessageType.VIDEO]: '视频',
|
[MessageType.VOICE]: 'voice',
|
||||||
[MessageType.FILE]: '文件',
|
[MessageType.VIDEO]: 'video',
|
||||||
[MessageType.EMOJI]: '表情',
|
[MessageType.FILE]: 'file',
|
||||||
[MessageType.LINK]: '链接',
|
[MessageType.EMOJI]: 'emoji',
|
||||||
[MessageType.LOCATION]: '位置',
|
[MessageType.LINK]: 'link',
|
||||||
[MessageType.RED_PACKET]: '红包',
|
[MessageType.LOCATION]: 'location',
|
||||||
[MessageType.TRANSFER]: '转账',
|
// 交互消息类型
|
||||||
[MessageType.POKE]: '拍一拍',
|
[MessageType.RED_PACKET]: 'redPacket',
|
||||||
[MessageType.CALL]: '通话',
|
[MessageType.TRANSFER]: 'transfer',
|
||||||
[MessageType.SHARE]: '分享',
|
[MessageType.POKE]: 'poke',
|
||||||
[MessageType.REPLY]: '回复',
|
[MessageType.CALL]: 'call',
|
||||||
[MessageType.FORWARD]: '转发',
|
[MessageType.SHARE]: 'share',
|
||||||
[MessageType.CONTACT]: '名片',
|
[MessageType.REPLY]: 'reply',
|
||||||
[MessageType.SYSTEM]: '系统',
|
[MessageType.FORWARD]: 'forward',
|
||||||
[MessageType.RECALL]: '撤回',
|
[MessageType.CONTACT]: 'contact',
|
||||||
[MessageType.OTHER]: '其他',
|
// 系统消息类型
|
||||||
|
[MessageType.SYSTEM]: 'system',
|
||||||
|
[MessageType.RECALL]: 'recall',
|
||||||
|
// 其他
|
||||||
|
[MessageType.OTHER]: 'other',
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 获取消息类型名称 */
|
/**
|
||||||
export function getMessageTypeName(type: MessageType | number): string {
|
* 获取消息类型名称
|
||||||
return MESSAGE_TYPE_NAMES[type] || '未知'
|
* @param type 消息类型
|
||||||
|
* @param t 可选的 i18n t 函数,传入时使用 common.messageType.* 键
|
||||||
|
*/
|
||||||
|
export function getMessageTypeName(type: MessageType | number, t?: (key: string) => string): string {
|
||||||
|
const key = MESSAGE_TYPE_KEYS[type]
|
||||||
|
if (t && key) return t(`common.messageType.${key}`)
|
||||||
|
return t ? t('common.messageType.unknown') : '未知'
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 小时活跃度 */
|
/** 小时活跃度 */
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* ECharts 日历热力图组件(GitHub 贡献图风格)
|
* ECharts 日历热力图组件(GitHub 贡献图风格)
|
||||||
*/
|
*/
|
||||||
import { computed, ref, watch, onMounted, onUnmounted } from 'vue'
|
import { computed, ref, watch, onMounted, onUnmounted } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
import * as echarts from 'echarts/core'
|
import * as echarts from 'echarts/core'
|
||||||
import { HeatmapChart } from 'echarts/charts'
|
import { HeatmapChart } from 'echarts/charts'
|
||||||
import { CalendarComponent, TooltipComponent, VisualMapComponent } from 'echarts/components'
|
import { CalendarComponent, TooltipComponent, VisualMapComponent } from 'echarts/components'
|
||||||
@@ -30,6 +31,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
height: 180,
|
height: 180,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { t, locale } = useI18n()
|
||||||
const isDark = useDark()
|
const isDark = useDark()
|
||||||
const chartRef = ref<HTMLElement | null>(null)
|
const chartRef = ref<HTMLElement | null>(null)
|
||||||
let chartInstance: echarts.ECharts | null = null
|
let chartInstance: echarts.ECharts | null = null
|
||||||
@@ -70,7 +72,7 @@ const option = computed<ECOption>(() => ({
|
|||||||
formatter: (params: any) => {
|
formatter: (params: any) => {
|
||||||
const date = params.data[0]
|
const date = params.data[0]
|
||||||
const value = params.data[1]
|
const value = params.data[1]
|
||||||
return `${date}<br/>消息: ${value}`
|
return `${date}<br/>${t('views.message.calendarTooltipMessages')}: ${value}`
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
visualMap: {
|
visualMap: {
|
||||||
@@ -111,13 +113,35 @@ const option = computed<ECOption>(() => ({
|
|||||||
show: true,
|
show: true,
|
||||||
color: isDark.value ? '#9ca3af' : '#6b7280',
|
color: isDark.value ? '#9ca3af' : '#6b7280',
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
|
nameMap: [
|
||||||
|
t('common.month.jan'),
|
||||||
|
t('common.month.feb'),
|
||||||
|
t('common.month.mar'),
|
||||||
|
t('common.month.apr'),
|
||||||
|
t('common.month.may'),
|
||||||
|
t('common.month.jun'),
|
||||||
|
t('common.month.jul'),
|
||||||
|
t('common.month.aug'),
|
||||||
|
t('common.month.sep'),
|
||||||
|
t('common.month.oct'),
|
||||||
|
t('common.month.nov'),
|
||||||
|
t('common.month.dec'),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
dayLabel: {
|
dayLabel: {
|
||||||
show: true,
|
show: true,
|
||||||
firstDay: 1, // 从周一开始
|
firstDay: 1, // 从周一开始
|
||||||
color: isDark.value ? '#6b7280' : '#9ca3af',
|
color: isDark.value ? '#6b7280' : '#9ca3af',
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
nameMap: ['日', '一', '二', '三', '四', '五', '六'],
|
nameMap: [
|
||||||
|
t('common.weekday.sun'),
|
||||||
|
t('common.weekday.mon'),
|
||||||
|
t('common.weekday.tue'),
|
||||||
|
t('common.weekday.wed'),
|
||||||
|
t('common.weekday.thu'),
|
||||||
|
t('common.weekday.fri'),
|
||||||
|
t('common.weekday.sat'),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
splitLine: {
|
splitLine: {
|
||||||
show: false,
|
show: false,
|
||||||
@@ -153,8 +177,8 @@ function handleResize() {
|
|||||||
chartInstance?.resize()
|
chartInstance?.resize()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听数据和主题变化
|
// 监听数据、主题、语言变化
|
||||||
watch([() => props.data, isDark], () => {
|
watch([() => props.data, isDark, locale], () => {
|
||||||
updateChart()
|
updateChart()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,28 @@
|
|||||||
"members": "members",
|
"members": "members",
|
||||||
"days": "days"
|
"days": "days"
|
||||||
},
|
},
|
||||||
|
"messageType": {
|
||||||
|
"text": "Text",
|
||||||
|
"image": "Image",
|
||||||
|
"voice": "Voice",
|
||||||
|
"video": "Video",
|
||||||
|
"file": "File",
|
||||||
|
"emoji": "Emoji",
|
||||||
|
"link": "Link",
|
||||||
|
"location": "Location",
|
||||||
|
"redPacket": "Red Packet",
|
||||||
|
"transfer": "Transfer",
|
||||||
|
"poke": "Poke",
|
||||||
|
"call": "Call",
|
||||||
|
"share": "Share",
|
||||||
|
"reply": "Reply",
|
||||||
|
"forward": "Forward",
|
||||||
|
"contact": "Contact",
|
||||||
|
"system": "System",
|
||||||
|
"recall": "Recalled",
|
||||||
|
"other": "Other",
|
||||||
|
"unknown": "Unknown"
|
||||||
|
},
|
||||||
"weekday": {
|
"weekday": {
|
||||||
"mon": "Mon",
|
"mon": "Mon",
|
||||||
"tue": "Tue",
|
"tue": "Tue",
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
"heatmapHint": "Shows chat time patterns",
|
"heatmapHint": "Shows chat time patterns",
|
||||||
"calendarHeatmap": "Message Calendar",
|
"calendarHeatmap": "Message Calendar",
|
||||||
"calendarHint": "Daily message distribution",
|
"calendarHint": "Daily message distribution",
|
||||||
|
"calendarTooltipMessages": "Messages",
|
||||||
"lengthDetailTitle": "Short Messages (1-25 chars)",
|
"lengthDetailTitle": "Short Messages (1-25 chars)",
|
||||||
"lengthDetailHint": "Per character",
|
"lengthDetailHint": "Per character",
|
||||||
"lengthGroupedTitle": "Length Range Distribution",
|
"lengthGroupedTitle": "Length Range Distribution",
|
||||||
|
|||||||
@@ -40,6 +40,28 @@
|
|||||||
"members": "个成员",
|
"members": "个成员",
|
||||||
"days": "天"
|
"days": "天"
|
||||||
},
|
},
|
||||||
|
"messageType": {
|
||||||
|
"text": "文字",
|
||||||
|
"image": "图片",
|
||||||
|
"voice": "语音",
|
||||||
|
"video": "视频",
|
||||||
|
"file": "文件",
|
||||||
|
"emoji": "表情",
|
||||||
|
"link": "链接",
|
||||||
|
"location": "位置",
|
||||||
|
"redPacket": "红包",
|
||||||
|
"transfer": "转账",
|
||||||
|
"poke": "拍一拍",
|
||||||
|
"call": "通话",
|
||||||
|
"share": "分享",
|
||||||
|
"reply": "回复",
|
||||||
|
"forward": "转发",
|
||||||
|
"contact": "名片",
|
||||||
|
"system": "系统",
|
||||||
|
"recall": "撤回",
|
||||||
|
"other": "其他",
|
||||||
|
"unknown": "未知"
|
||||||
|
},
|
||||||
"weekday": {
|
"weekday": {
|
||||||
"mon": "周一",
|
"mon": "周一",
|
||||||
"tue": "周二",
|
"tue": "周二",
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
"heatmapHint": "展示聊天时间规律",
|
"heatmapHint": "展示聊天时间规律",
|
||||||
"calendarHeatmap": "消息日历",
|
"calendarHeatmap": "消息日历",
|
||||||
"calendarHint": "每日消息分布",
|
"calendarHint": "每日消息分布",
|
||||||
|
"calendarTooltipMessages": "消息",
|
||||||
"lengthDetailTitle": "短消息分布 (1-25字)",
|
"lengthDetailTitle": "短消息分布 (1-25字)",
|
||||||
"lengthDetailHint": "逐字统计",
|
"lengthDetailHint": "逐字统计",
|
||||||
"lengthGroupedTitle": "长度区间分布",
|
"lengthGroupedTitle": "长度区间分布",
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ const { dailyChartData } = useDailyTrend(props.dailyActivity)
|
|||||||
// 消息类型图表数据
|
// 消息类型图表数据
|
||||||
const typeChartData = computed<EChartPieData>(() => {
|
const typeChartData = computed<EChartPieData>(() => {
|
||||||
return {
|
return {
|
||||||
labels: props.messageTypes.map((t) => getMessageTypeName(t.type)),
|
labels: props.messageTypes.map((item) => getMessageTypeName(item.type, t)),
|
||||||
values: props.messageTypes.map((t) => t.count),
|
values: props.messageTypes.map((item) => item.count),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ onMounted(() => {
|
|||||||
icon="i-heroicons-plus-circle"
|
icon="i-heroicons-plus-circle"
|
||||||
@click="showIncrementalImportModal = true"
|
@click="showIncrementalImportModal = true"
|
||||||
>
|
>
|
||||||
{{ t('analysis.incrementalImport', '增量导入') }}
|
{{ t('analysis.tooltip.incrementalImport') }}
|
||||||
</UButton>
|
</UButton>
|
||||||
<UButton
|
<UButton
|
||||||
color="primary"
|
color="primary"
|
||||||
@@ -217,7 +217,7 @@ onMounted(() => {
|
|||||||
icon="i-heroicons-chat-bubble-bottom-center-text"
|
icon="i-heroicons-chat-bubble-bottom-center-text"
|
||||||
@click="openChatRecordViewer"
|
@click="openChatRecordViewer"
|
||||||
>
|
>
|
||||||
{{ t('analysis.chatViewer', '聊天记录查看器') }}
|
{{ t('analysis.tooltip.chatViewer') }}
|
||||||
</UButton>
|
</UButton>
|
||||||
<UTooltip :text="t('analysis.tooltip.sessionIndex')">
|
<UTooltip :text="t('analysis.tooltip.sessionIndex')">
|
||||||
<UButton
|
<UButton
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ const { dailyChartData } = useDailyTrend(props.dailyActivity)
|
|||||||
// 消息类型图表数据
|
// 消息类型图表数据
|
||||||
const typeChartData = computed<EChartPieData>(() => {
|
const typeChartData = computed<EChartPieData>(() => {
|
||||||
return {
|
return {
|
||||||
labels: props.messageTypes.map((t) => getMessageTypeName(t.type)),
|
labels: props.messageTypes.map((item) => getMessageTypeName(item.type, t)),
|
||||||
values: props.messageTypes.map((t) => t.count),
|
values: props.messageTypes.map((item) => item.count),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ onMounted(() => {
|
|||||||
icon="i-heroicons-plus-circle"
|
icon="i-heroicons-plus-circle"
|
||||||
@click="showIncrementalImportModal = true"
|
@click="showIncrementalImportModal = true"
|
||||||
>
|
>
|
||||||
{{ t('analysis.incrementalImport', '增量导入') }}
|
{{ t('analysis.tooltip.incrementalImport') }}
|
||||||
</UButton>
|
</UButton>
|
||||||
<UButton
|
<UButton
|
||||||
color="primary"
|
color="primary"
|
||||||
@@ -229,7 +229,7 @@ onMounted(() => {
|
|||||||
icon="i-heroicons-chat-bubble-bottom-center-text"
|
icon="i-heroicons-chat-bubble-bottom-center-text"
|
||||||
@click="openChatRecordViewer"
|
@click="openChatRecordViewer"
|
||||||
>
|
>
|
||||||
{{ t('analysis.chatViewer', '聊天记录查看器') }}
|
{{ t('analysis.tooltip.chatViewer') }}
|
||||||
</UButton>
|
</UButton>
|
||||||
<UTooltip :text="t('analysis.tooltip.sessionIndex')">
|
<UTooltip :text="t('analysis.tooltip.sessionIndex')">
|
||||||
<UButton
|
<UButton
|
||||||
|
|||||||
@@ -44,40 +44,43 @@ export enum MessageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 消息类型名称映射
|
* 消息类型 i18n key 映射
|
||||||
*/
|
*/
|
||||||
export const MESSAGE_TYPE_NAMES: Record<number, string> = {
|
const MESSAGE_TYPE_KEYS: Record<number, string> = {
|
||||||
// 基础消息类型
|
// 基础消息类型
|
||||||
[MessageType.TEXT]: '文字',
|
[MessageType.TEXT]: 'text',
|
||||||
[MessageType.IMAGE]: '图片',
|
[MessageType.IMAGE]: 'image',
|
||||||
[MessageType.VOICE]: '语音',
|
[MessageType.VOICE]: 'voice',
|
||||||
[MessageType.VIDEO]: '视频',
|
[MessageType.VIDEO]: 'video',
|
||||||
[MessageType.FILE]: '文件',
|
[MessageType.FILE]: 'file',
|
||||||
[MessageType.EMOJI]: '表情',
|
[MessageType.EMOJI]: 'emoji',
|
||||||
[MessageType.LINK]: '链接',
|
[MessageType.LINK]: 'link',
|
||||||
[MessageType.LOCATION]: '位置',
|
[MessageType.LOCATION]: 'location',
|
||||||
// 交互消息类型
|
// 交互消息类型
|
||||||
[MessageType.RED_PACKET]: '红包',
|
[MessageType.RED_PACKET]: 'redPacket',
|
||||||
[MessageType.TRANSFER]: '转账',
|
[MessageType.TRANSFER]: 'transfer',
|
||||||
[MessageType.POKE]: '拍一拍',
|
[MessageType.POKE]: 'poke',
|
||||||
[MessageType.CALL]: '通话',
|
[MessageType.CALL]: 'call',
|
||||||
[MessageType.SHARE]: '分享',
|
[MessageType.SHARE]: 'share',
|
||||||
[MessageType.REPLY]: '回复',
|
[MessageType.REPLY]: 'reply',
|
||||||
[MessageType.FORWARD]: '转发',
|
[MessageType.FORWARD]: 'forward',
|
||||||
[MessageType.CONTACT]: '名片',
|
[MessageType.CONTACT]: 'contact',
|
||||||
// 系统消息类型
|
// 系统消息类型
|
||||||
[MessageType.SYSTEM]: '系统',
|
[MessageType.SYSTEM]: 'system',
|
||||||
[MessageType.RECALL]: '撤回',
|
[MessageType.RECALL]: 'recall',
|
||||||
// 其他
|
// 其他
|
||||||
[MessageType.OTHER]: '其他',
|
[MessageType.OTHER]: 'other',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取消息类型名称
|
* 获取消息类型名称
|
||||||
* @param type 消息类型
|
* @param type 消息类型
|
||||||
|
* @param t 可选的 i18n t 函数,传入时使用 common.messageType.* 键
|
||||||
*/
|
*/
|
||||||
export function getMessageTypeName(type: MessageType | number): string {
|
export function getMessageTypeName(type: MessageType | number, t?: (key: string) => string): string {
|
||||||
return MESSAGE_TYPE_NAMES[type] || '未知'
|
const key = MESSAGE_TYPE_KEYS[type]
|
||||||
|
if (t && key) return t(`common.messageType.${key}`)
|
||||||
|
return t ? t('common.messageType.unknown') : '未知'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user