|
@@ -62,6 +62,19 @@ const viewMode = ref('chart');
|
|
|
const sortMode = ref('count');
|
|
|
const allBuckets = ref({});
|
|
|
|
|
|
+// 添加缓存变量
|
|
|
+const cachedData = ref({
|
|
|
+ chart: null,
|
|
|
+ table: {
|
|
|
+ data: [],
|
|
|
+ pagination: {
|
|
|
+ current: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ total: 0,
|
|
|
+ }
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
// 定义表格列
|
|
|
const columns = [
|
|
|
{
|
|
@@ -144,106 +157,122 @@ const initChart = () => {
|
|
|
};
|
|
|
|
|
|
const updateChart = async () => {
|
|
|
- const params = {
|
|
|
- sort: sortMode.value,
|
|
|
- page: 1,
|
|
|
- page_size: 10,
|
|
|
- ...props.queryParam,
|
|
|
- };
|
|
|
-
|
|
|
- try {
|
|
|
- const res = await getOrigCountryReport(params);
|
|
|
+ // 如果有缓存且排序模式没变,直接使用缓存
|
|
|
+ if (cachedData.value.chart) {
|
|
|
+ chartData.value = cachedData.value.chart;
|
|
|
+ allBuckets.value = cachedData.value.allBuckets;
|
|
|
+ } else {
|
|
|
+ const params = {
|
|
|
+ sort: sortMode.value,
|
|
|
+ page: 1,
|
|
|
+ page_size: 10,
|
|
|
+ ...props.queryParam,
|
|
|
+ };
|
|
|
|
|
|
- if (res && res.result && res.result.data && res.result.data.result && res.result.data.result.buckets) {
|
|
|
- chartData.value = res.result.data.result.buckets;
|
|
|
- allBuckets.value = res.result.data.result.allBuckets;
|
|
|
- } else {
|
|
|
- console.error('Unexpected API response structure:', res);
|
|
|
- return; // Exit if the response structure is not as expected
|
|
|
+ try {
|
|
|
+ const res = await getOrigCountryReport(params);
|
|
|
+ if (res?.result?.data?.result?.buckets) {
|
|
|
+ chartData.value = res.result.data.result.buckets;
|
|
|
+ // 保存到缓存
|
|
|
+ cachedData.value.chart = res.result.data.result.buckets;
|
|
|
+ cachedData.value.allBuckets = res.result.data.result.allBuckets;
|
|
|
+ allBuckets.value = res.result.data.result.allBuckets;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error('Failed to fetch data:', error);
|
|
|
+ return;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- const valueKeyMap = {
|
|
|
- count: 'count',
|
|
|
- weight: 'sum_weight',
|
|
|
- amount: 'sum_amount',
|
|
|
- };
|
|
|
+ // 无论是否使用缓存,都执行以下图表渲染逻辑
|
|
|
+ const valueKeyMap = {
|
|
|
+ count: 'count',
|
|
|
+ weight: 'sum_weight',
|
|
|
+ amount: 'sum_amount',
|
|
|
+ };
|
|
|
|
|
|
- // 获取前10个数据并计算总数
|
|
|
- const data = chartData.value.sort((a, b) => Number(b[valueKeyMap[sortMode.value]]) - Number(a[valueKeyMap[sortMode.value]]));
|
|
|
+ // 获取前10个数据并计算总数
|
|
|
+ const data = chartData.value.sort((a, b) => Number(b[valueKeyMap[sortMode.value]]) - Number(a[valueKeyMap[sortMode.value]]));
|
|
|
|
|
|
- // 根据 sortMode 映射到 allBuckets 的对应关系
|
|
|
- const totalKeyMap = {
|
|
|
- count: 'count',
|
|
|
- weight: 'weight_sum',
|
|
|
- amount: 'amount_sum',
|
|
|
- };
|
|
|
+ // 根据 sortMode 映射到 allBuckets 的对应关系
|
|
|
+ const totalKeyMap = {
|
|
|
+ count: 'count',
|
|
|
+ weight: 'weight_sum',
|
|
|
+ amount: 'amount_sum',
|
|
|
+ };
|
|
|
|
|
|
- const total = allBuckets.value[totalKeyMap[sortMode.value]] || 0; // 使用映射获取总数
|
|
|
- const otherCount = total - data.reduce((sum, item) => sum + Number(item[valueKeyMap[sortMode.value]]), 0);
|
|
|
+ const total = allBuckets.value[totalKeyMap[sortMode.value]] || 0;
|
|
|
+ const otherCount = total - data.reduce((sum, item) => sum + Number(item[valueKeyMap[sortMode.value]]), 0);
|
|
|
|
|
|
- const option = {
|
|
|
- tooltip: {
|
|
|
- trigger: 'item',
|
|
|
- formatter: (params) => {
|
|
|
- const percent = ((params.value / total) * 100).toFixed(2);
|
|
|
- return `${params.name}<br/>${sortMode.value === 'count' ? '交易次数' : sortMode.value === 'weight' ? '交易重量' : '交易金额'}: ${formatNumber(params.value)}<br/>占比: ${percent}%`;
|
|
|
- },
|
|
|
+ const option = {
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'item',
|
|
|
+ formatter: (params) => {
|
|
|
+ const percent = ((params.value / total) * 100).toFixed(2);
|
|
|
+ return `${params.name}<br/>${sortMode.value === 'count' ? '交易次数' : sortMode.value === 'weight' ? '交易重量' : '交易金额'}: ${formatNumber(params.value)}<br/>占比: ${percent}%`;
|
|
|
},
|
|
|
- legend: {
|
|
|
- orient: 'vertical',
|
|
|
- right: 10,
|
|
|
- top: 'center',
|
|
|
- type: 'scroll',
|
|
|
- },
|
|
|
- series: [
|
|
|
- {
|
|
|
- name: '交易次数',
|
|
|
- type: 'pie',
|
|
|
- radius: ['40%', '70%'],
|
|
|
- avoidLabelOverlap: true,
|
|
|
- itemStyle: {
|
|
|
- borderRadius: 10,
|
|
|
- borderColor: '#fff',
|
|
|
- borderWidth: 2,
|
|
|
+ },
|
|
|
+ legend: {
|
|
|
+ orient: 'vertical',
|
|
|
+ right: 10,
|
|
|
+ top: 'center',
|
|
|
+ type: 'scroll',
|
|
|
+ },
|
|
|
+ series: [
|
|
|
+ {
|
|
|
+ name: '交易次数',
|
|
|
+ type: 'pie',
|
|
|
+ radius: ['40%', '70%'],
|
|
|
+ avoidLabelOverlap: true,
|
|
|
+ itemStyle: {
|
|
|
+ borderRadius: 10,
|
|
|
+ borderColor: '#fff',
|
|
|
+ borderWidth: 2,
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ show: true,
|
|
|
+ formatter: (params) => {
|
|
|
+ const percent = total > 0 ? ((params.value / total) * 100).toFixed(2) : 0.00;
|
|
|
+ return `${params.name}\n${percent}%`;
|
|
|
},
|
|
|
+ },
|
|
|
+ emphasis: {
|
|
|
label: {
|
|
|
show: true,
|
|
|
- formatter: (params) => {
|
|
|
- const percent = total > 0 ? ((params.value / total) * 100).toFixed(2) : 0.00;
|
|
|
- return `${params.name}\n${percent}%`;
|
|
|
- },
|
|
|
- },
|
|
|
- emphasis: {
|
|
|
- label: {
|
|
|
- show: true,
|
|
|
- fontSize: 14,
|
|
|
- fontWeight: 'bold',
|
|
|
- },
|
|
|
+ fontSize: 14,
|
|
|
+ fontWeight: 'bold',
|
|
|
},
|
|
|
- data: [
|
|
|
- ...data.map((item) => ({
|
|
|
- name: item.val_cn || item.val,
|
|
|
- value: Number(item[valueKeyMap[sortMode.value]]),
|
|
|
- })),
|
|
|
- {
|
|
|
- name: '其他',
|
|
|
- value: otherCount,
|
|
|
- },
|
|
|
- ],
|
|
|
},
|
|
|
- ],
|
|
|
- };
|
|
|
+ data: [
|
|
|
+ ...data.map((item) => ({
|
|
|
+ name: item.val_cn || item.val,
|
|
|
+ value: Number(item[valueKeyMap[sortMode.value]]),
|
|
|
+ })),
|
|
|
+ {
|
|
|
+ name: '其他',
|
|
|
+ value: otherCount,
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ },
|
|
|
+ ],
|
|
|
+ };
|
|
|
|
|
|
- nextTick(() => {
|
|
|
- setOptions(option, true, true);
|
|
|
- });
|
|
|
- } catch (error) {
|
|
|
- console.error('Failed to fetch data:', error);
|
|
|
- }
|
|
|
+ nextTick(() => {
|
|
|
+ setOptions(option, true, true);
|
|
|
+ });
|
|
|
};
|
|
|
|
|
|
-// Replace registerTransactionTable with this new method
|
|
|
+// 修改 handleTableChange 函数
|
|
|
async function handleTableChange(pag, filters, sorter) {
|
|
|
+ // 检查缓存中是否有当前页的数据
|
|
|
+ if (cachedData.value.table.data.length > 0 &&
|
|
|
+ cachedData.value.table.pagination.current === pag.current &&
|
|
|
+ cachedData.value.table.pagination.pageSize === pag.pageSize) {
|
|
|
+ pagination.value = cachedData.value.table.pagination;
|
|
|
+ tableData.value = cachedData.value.table.data;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
loading.value = true;
|
|
|
try {
|
|
|
const params = {
|
|
@@ -254,12 +283,18 @@ async function handleTableChange(pag, filters, sorter) {
|
|
|
};
|
|
|
|
|
|
const res = await getOrigCountryReport(params);
|
|
|
- if (res.result.data.result && res.result.data.result.buckets) {
|
|
|
- pagination.value = {
|
|
|
+ if (res.result.data.result?.buckets) {
|
|
|
+ const newPagination = {
|
|
|
current: pag.current,
|
|
|
pageSize: pag.pageSize,
|
|
|
total: res.result.data.result.numBuckets || 0,
|
|
|
};
|
|
|
+ // 更新缓存
|
|
|
+ cachedData.value.table = {
|
|
|
+ data: res.result.data.result.buckets,
|
|
|
+ pagination: newPagination
|
|
|
+ };
|
|
|
+ pagination.value = newPagination;
|
|
|
tableData.value = res.result.data.result.buckets;
|
|
|
}
|
|
|
} catch (error) {
|
|
@@ -269,20 +304,7 @@ async function handleTableChange(pag, filters, sorter) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 监听数据变化
|
|
|
-watch(
|
|
|
- () => props.queryParam,
|
|
|
- () => {
|
|
|
- if (viewMode.value === 'chart') {
|
|
|
- updateChart();
|
|
|
- } else {
|
|
|
- handleTableChange(pagination.value, {}, {});
|
|
|
- }
|
|
|
- },
|
|
|
- { deep: true }
|
|
|
-);
|
|
|
-
|
|
|
-// 监听视图模式变化
|
|
|
+// 修改视图模式监听
|
|
|
watch(viewMode, (newValue) => {
|
|
|
if (newValue === 'chart') {
|
|
|
updateChart();
|
|
@@ -291,7 +313,12 @@ watch(viewMode, (newValue) => {
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+// 修改排序模式监听,清除缓存并重新获取数据
|
|
|
watch(sortMode, () => {
|
|
|
+ // 清除缓存
|
|
|
+ cachedData.value.chart = null;
|
|
|
+ cachedData.value.table.data = [];
|
|
|
+
|
|
|
if (viewMode.value === 'chart') {
|
|
|
updateChart();
|
|
|
} else {
|
|
@@ -299,6 +326,23 @@ watch(sortMode, () => {
|
|
|
}
|
|
|
});
|
|
|
|
|
|
+// 监听查询参数变化,清除缓存并重新获取数据
|
|
|
+watch(
|
|
|
+ () => props.queryParam,
|
|
|
+ () => {
|
|
|
+ // 清除缓存
|
|
|
+ cachedData.value.chart = null;
|
|
|
+ cachedData.value.table.data = [];
|
|
|
+
|
|
|
+ if (viewMode.value === 'chart') {
|
|
|
+ updateChart();
|
|
|
+ } else {
|
|
|
+ handleTableChange(pagination.value, {}, {});
|
|
|
+ }
|
|
|
+ },
|
|
|
+ { deep: true }
|
|
|
+);
|
|
|
+
|
|
|
onMounted(() => {
|
|
|
if (viewMode.value === 'chart') {
|
|
|
initChart();
|