You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

343 lines
8.3 KiB

<template>
<div class="cash-management">
<div class="cash-title">
<div class="text1">
现金管理
<!-- <span class="text1-update-time">-->
<!-- 最后更新时间{{ workDataUpdateTime || '该地区暂无数据' }}-->
<!-- </span>-->
<el-popover
placement="top-start"
title="数据说明"
:width="240"
trigger="hover"
content="此数据实时计算,存在误差,请勿作为最终数据使用。"
>
<template #reference>
<el-icon
class="service-icon"
style="
margin-left: 5px;
cursor: pointer;
font-size: 16px;
transition: all 0.3s ease;">
<Warning/>
</el-icon>
</template>
</el-popover>
</div>
</div>
<div class=" text2
">
<span class="text2-income">总营收{{ totalIncome.toFixed(2) }} 新币</span>
</div>
<div class="chart-container">
<!-- 左侧数据列表 -->
<div class="market-data">
<div v-if="marksFlag" v-for="market in cashData.markets" :key="market.name" class="market-item">
<span class="market-name">{{ market.name }}:</span>
<span class="market-value">{{ market.value.toLocaleString() }} 新币</span>
</div>
<div v-else v-for="item in cashData.markets" :key="item.name" class="market-item">
<span class="market-name">代收{{ item.name }}:</span>
<span class="market-value">{{ item.value.toLocaleString() }} </span>
</div>
</div>
<!-- 图表 -->
<div ref="chartRef" class="chart"></div>
</div>
</div>
</template>
<script setup>
import * as echarts from 'echarts'
import {onMounted, ref} from 'vue'
import request from "@/util/http.js";
import API from "@/util/http.js";
import {Warning, Service} from "@element-plus/icons-vue";
const chartRef = ref(null)
let chartInstance = null
// 响应式数据
const cashData = ref({
markets: []
})
const markets = ref()
// 定义默认市场
const defaultMarkets = [
{name: '新加坡', value: 0},
{name: '马来西亚', value: 0},
{name: '香港', value: 0},
{name: '泰国', value: 0},
{name: '越南HCM', value: 0},
{name: '加拿大', value: 0},
// {name: '未知', value: 0},
// { name: '其他', value: 0 },
// {name: '市场部', value: 0},
// { name: '深圳运营', value: 0 },
// { name: '研发部', value: 0 },
]
const workDataUpdateTime = ref('')
const totalIncome = ref(0)
// 获取当前年份
const currentYear = new Date().getFullYear();
// 本年第一天 00:00:00
const startDate = `${currentYear}-01-01 00:00:00`;
// 本年最后一天 23:59:59
const endDate = `${currentYear}-12-31 23:59:59`;
// 获取接口数据
const fetchCashData = async () => {
getAdminData()
try {
const res = await request({
url: '/workbench/getTotalRevenue',
method: 'POST',
data: {
startDate: startDate,
endDate: endDate
}
})
console.log("jjjjjjj", res.market)
// const data = res
console.log("jjjjjjj", res)
// 总新币
console.log("totalIncome", res)
totalIncome.value = res.reduce((sum, item) => {
return sum + (item.totalSGD || 0);
}, 0);
// 格式化数据
if (marksFlag.value) {
// 生成接口数据映射表
const resMap = new Map(
res.map(item => [item.market, Number(item.totalSGD) || 0])
)
// 合并:优先用接口数据,否则默认 0
markets.value = defaultMarkets.map(m => ({
name: m.name,
value: resMap.get(m.name) ?? 0
}))
} else if (marksFlag.value=== false) {
// 1. 定义币种中英文对照表
const currencyMap = {
sgd: '新币',
myr: '马币',
hkd: '港币',
cad: '加币',
thb: '泰铢',
vdn: '越南盾',
};
// 2. 取出所有币种字段(排除 market 与 totalSGD),只保留 currencyMap 中定义的币种
const currencyKeys =
res.length > 0
? Object.keys(res[0]).filter(
key =>
key !== 'market' &&
key !== 'totalSGD' &&
Object.keys(currencyMap).includes(key.toLowerCase())
)
: Object.keys(currencyMap);
// 3. 累加每个币种的总额并替换中文名
markets.value = currencyKeys.map(currency => {
const lowerCurrency = currency.toLowerCase();
const total =
res.length > 0
? res.reduce((sum, item) => sum + (Number(item[currency]) || 0), 0)
: 0;
return {
name: currencyMap[lowerCurrency],
value: total,
};
});
}
// 更新数据
cashData.value.markets = markets.value
console.log("cashData", cashData.value.markets)
// // 使用reduce方法遍历markets数组,将所有市场的value值累加,赋值给totalIncome响应式变量
// totalIncome.value = markets.value.reduce((sum, cur) => sum + cur.value, 0)
// workDataUpdateTime.value = new Date().toLocaleString('zh-CN', { hour12: false })
renderChart()
} catch (err) {
console.error('获取数据失败:', err)
}
}
// 标记地区 为 研发部、总部时值为
const marksFlag = ref();
const loading = ref(true); // 新增加载状态
const getAdminData = async function () {
try {
loading.value = true; // 开始加载
const result = await API({url: '/admin/userinfo', data: {}});
marksFlag.value = result.markets === '总部' || result.markets === '研发部';
console.log("marksFlag", marksFlag.value);
// alert(marksFlag.value)
} catch (error) {
console.log('请求失败', error);
} finally {
loading.value = false; // 无论成功失败都结束加载
}
};
// 渲染饼图
const renderChart = () => {
if (!chartRef.value) return
if (!chartInstance) chartInstance = echarts.init(chartRef.value)
const option = {
tooltip: {trigger: 'item'},
legend: {
bottom: 5,
icon: 'circle',
left: 'center'
},
series: [
{
label: {show: false},
type: 'pie',
radius: ['40%', '70%'],
data: cashData.value.markets,
center: ['60%', '45%']
}
]
}
chartInstance.setOption(option)
}
onMounted(() => {
// getAdminData()
fetchCashData()
})
</script>
<style scoped>
/* 保留你原来的样式 */
.cash-management {
margin: 10px 5px;
width: 100%;
height: 550px;
border-radius: 8px;
background: #E7F4FD;
box-shadow: 0 2px 2px 0 #00000040;
display: flex;
flex-direction: column;
align-items: center;
}
.cash-title {
width: 100%;
height: 5vh;
flex-shrink: 0;
border-radius: 8px;
background: linear-gradient(90deg, #E4F0FC 0%, #C6ADFF 50%, #E4F0FC 100%);
box-shadow: 0 2px 2px 0 #00152940;
display: flex;
align-items: center;
justify-content: center;
}
.text1 {
color: #040a2d;
font-family: "PingFang SC";
font-size: 28px;
font-weight: 900;
}
.text1-update-time {
margin-left: 10px;
color: #040a2d;
font-size: 20px;
font-weight: 700;
}
.text2 {
margin: 13px;
width: 95%;
height: 48px;
border-radius: 8px;
background: linear-gradient(90deg, #E4F0FC 0%, #C1DCF8 50%, #E4F0FC 100%);
box-shadow: 0 2px 2px 0 #00152940;
display: flex;
align-items: center;
justify-content: center;
}
.text2-income {
color: #040a2d;
font-size: 20px;
font-weight: 900;
}
.chart-container {
display: flex;
align-items: center;
width: 100%;
height: 100%;
padding: 10px;
}
.market-data {
display: flex;
width: 245px;
flex-direction: column;
align-items: flex-start;
gap: 20px;
padding: 10px;
margin-left: 40px;
}
.market-item {
display: flex;
justify-content: space-between;
width: 100%;
font-family: "PingFang SC";
font-size: 16px;
color: #040a2d;
white-space: nowrap; /* 禁止换行 */
overflow: hidden; /* 隐藏溢出内容 */
text-overflow: ellipsis; /* 溢出显示省略号 */
margin-bottom: 8px; /* 增加项间距,提升可读性 */
}
.market-name {
flex: 0 0 auto; /* 名称部分自适应宽度 */
margin-right: 16px; /* 与金额保持距离 */
}
.market-value {
flex: 1; /* 金额部分占剩余宽度 */
text-align: right;
}
.chart {
flex: 1;
height: 300px;
width: auto;
margin-top: 10px;
}
</style>