feat(i18n): 管理端与玩家端三语支持(中/英/马来语)
- 管理后台 adminT 文案库、结算与代理端页面、表单校验 - 玩家端 vue-i18n 补全首页/公告/串关与 ms 文案 - Element Plus ms 语言包与共享 locale 工具
This commit is contained in:
@@ -1,6 +1,18 @@
|
||||
import type { EChartsOption } from 'echarts';
|
||||
import type { AdminLocale } from '../i18n/admin-messages';
|
||||
import { formatAmount, formatAmountFull } from './format-amount';
|
||||
|
||||
export type ChartI18n = {
|
||||
locale?: AdminLocale;
|
||||
betCountSeries: string;
|
||||
axisAmount: string;
|
||||
axisCount: string;
|
||||
countSuffix: string;
|
||||
pieTooltip: string;
|
||||
noData: string;
|
||||
pieEmpty: string;
|
||||
};
|
||||
|
||||
const tooltipBase = {
|
||||
backgroundColor: '#141414',
|
||||
borderColor: '#2a2a2a',
|
||||
@@ -110,7 +122,10 @@ export function buildMultiLineChartOption(
|
||||
export function buildPieChartOption(
|
||||
title: string,
|
||||
segments: PieSegment[],
|
||||
i18n?: Partial<ChartI18n>,
|
||||
): EChartsOption {
|
||||
const loc = i18n?.locale;
|
||||
const noData = i18n?.noData ?? '暂无数据';
|
||||
const data = segments.map((s) => ({
|
||||
name: s.label,
|
||||
value: s.value,
|
||||
@@ -122,7 +137,7 @@ export function buildPieChartOption(
|
||||
tooltip: {
|
||||
...tooltipBase,
|
||||
trigger: 'item',
|
||||
formatter: '{b}:{c}({d}%)',
|
||||
formatter: i18n?.pieTooltip ?? '{b}:{c}({d}%)',
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
@@ -151,14 +166,15 @@ export function buildPieChartOption(
|
||||
label: { fontSize: 12, fontWeight: 'bold' },
|
||||
scaleSize: 6,
|
||||
},
|
||||
data: data.length ? data : [{ name: '暂无数据', value: 1, itemStyle: { color: '#333' } }],
|
||||
data: data.length ? data : [{ name: noData, value: 1, itemStyle: { color: '#333' } }],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
function fmtCount(v: number) {
|
||||
return v.toLocaleString('zh-CN', { maximumFractionDigits: 0 });
|
||||
function fmtCount(v: number, locale?: AdminLocale) {
|
||||
const tag = locale ?? 'zh-CN';
|
||||
return v.toLocaleString(tag, { maximumFractionDigits: 0 });
|
||||
}
|
||||
|
||||
/** 7 日金额折线 + 注单柱(双 Y 轴),一图看清趋势 */
|
||||
@@ -166,7 +182,11 @@ export function buildCombinedTrendOption(
|
||||
labels: string[],
|
||||
amountSeries: ChartSeries[],
|
||||
betCounts: number[],
|
||||
i18n: ChartI18n,
|
||||
): EChartsOption {
|
||||
const loc = i18n.locale;
|
||||
const betCountName = i18n.betCountSeries;
|
||||
const countSuffix = i18n.countSuffix;
|
||||
return {
|
||||
backgroundColor: 'transparent',
|
||||
color: [...amountSeries.map((s) => s.color), '#fb923c'],
|
||||
@@ -178,9 +198,10 @@ export function buildCombinedTrendOption(
|
||||
return items
|
||||
.map((p) => {
|
||||
const v = Number(p.value ?? 0);
|
||||
const isCount = p.seriesName === '注单笔数';
|
||||
const val = isCount ? `${fmtCount(v)} 笔` : formatAmountFull(v);
|
||||
return `${p.marker ?? ''}${p.seriesName}:${val}`;
|
||||
const isCount = p.seriesName === betCountName;
|
||||
const val = isCount ? `${fmtCount(v, loc)} ${countSuffix}` : formatAmountFull(v, loc);
|
||||
const sep = loc?.startsWith('zh') ? ':' : ': ';
|
||||
return `${p.marker ?? ''}${p.seriesName}${sep}${val}`;
|
||||
})
|
||||
.join('<br/>');
|
||||
},
|
||||
@@ -202,16 +223,16 @@ export function buildCombinedTrendOption(
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
name: '金额',
|
||||
name: i18n.axisAmount,
|
||||
nameTextStyle: { color: '#666', fontSize: 10 },
|
||||
axisLabel: { ...axisLabel, formatter: (v: number) => formatAmount(v) },
|
||||
axisLabel: { ...axisLabel, formatter: (v: number) => formatAmount(v, 2, loc) },
|
||||
splitLine,
|
||||
},
|
||||
{
|
||||
type: 'value',
|
||||
name: '笔数',
|
||||
name: i18n.axisCount,
|
||||
nameTextStyle: { color: '#666', fontSize: 10 },
|
||||
axisLabel: { ...axisLabel, formatter: (v: number) => fmtCount(v) },
|
||||
axisLabel: { ...axisLabel, formatter: (v: number) => fmtCount(v, loc) },
|
||||
splitLine: { show: false },
|
||||
},
|
||||
],
|
||||
@@ -228,7 +249,7 @@ export function buildCombinedTrendOption(
|
||||
lineStyle: { color: s.color, width: 2 },
|
||||
})),
|
||||
{
|
||||
name: '注单笔数',
|
||||
name: betCountName,
|
||||
type: 'bar',
|
||||
yAxisIndex: 1,
|
||||
data: betCounts,
|
||||
@@ -242,7 +263,10 @@ export function buildCombinedTrendOption(
|
||||
/** 三个饼图并排,占一张图 */
|
||||
export function buildTriplePieOption(
|
||||
blocks: { title: string; segments: PieSegment[] }[],
|
||||
i18n?: Partial<ChartI18n>,
|
||||
): EChartsOption {
|
||||
const pieEmpty = i18n?.pieEmpty ?? '暂无';
|
||||
const pieTooltip = i18n?.pieTooltip ?? '{b}:{c}({d}%)';
|
||||
const slots = [
|
||||
{ center: ['18%', '58%'] as [string, string], titleLeft: '14%' },
|
||||
{ center: ['50%', '58%'] as [string, string], titleLeft: '46%' },
|
||||
@@ -254,7 +278,7 @@ export function buildTriplePieOption(
|
||||
tooltip: {
|
||||
...tooltipBase,
|
||||
trigger: 'item',
|
||||
formatter: '{b}:{c}({d}%)',
|
||||
formatter: pieTooltip,
|
||||
},
|
||||
graphic: blocks.map((b, i) => ({
|
||||
type: 'text' as const,
|
||||
@@ -283,7 +307,7 @@ export function buildTriplePieOption(
|
||||
labelLine: { show: false },
|
||||
data: data.length
|
||||
? data
|
||||
: [{ name: '暂无', value: 1, itemStyle: { color: '#333' } }],
|
||||
: [{ name: pieEmpty, value: 1, itemStyle: { color: '#333' } }],
|
||||
};
|
||||
}),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user