Files
im-uniapp/pages/workbench/profit/components/ProfitList.vue
2025-08-20 16:07:18 +08:00

342 lines
7.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<!-- 列表内容区域 -->
<view class="list-container">
<uni-skeleton
v-if="loading"
:row="5"
:loading="loading"
title
avatar
></uni-skeleton>
<view v-else-if="profitList.length === 0" class="empty-view">
<uni-icons type="empty" size="60" color="#ccc"></uni-icons>
<text class="empty-text">暂无数据</text>
</view>
<view class="project-card" v-for="(item, index) in profitList" :key="index">
<view class="card-header">
<view class="header-left">
<text class="project-name">{{ item.projectName }}</text>
<text class="project-num">{{ item.projectNum }}</text>
</view>
<uni-tag
:text="item.projectStatus === '0' ? '进行中' : '完结'"
:type="item.projectStatus === '0' ? 'success' : 'primary'"
size="small"
></uni-tag>
</view>
<view class="card-body">
<view class="info-row">
<text class="info-label">贸易类型</text>
<text class="info-value">{{ getTradeTypeName(item.tradeType) }}</text>
</view>
<view class="info-row">
<text class="info-label">合同金额</text>
<text class="info-value">{{ item.originalFunds || item.detailIncome }}</text>
</view>
<view class="info-row">
<text class="info-label">人民币金额</text>
<text class="info-value">¥{{ item.totalIncomeCny }}</text>
</view>
<view class="info-row">
<text class="info-label">启动时间</text>
<text class="info-value">{{ item.beginTime }}</text>
</view>
</view>
<view class="card-footer">
<view class="profit-info" :style="getProfitLossStyle(item)">
<text class="profit-label">盈亏金额</text>
<text class="profit-value">{{ parseFloat(item.profitLoss || 0).toFixed(2) }}</text>
</view>
<uni-tag
v-if="getProfitRate(item) !== null"
:text="getProfitRateTag(item)"
:type="getProfitRateType(item)"
size="small"
></uni-tag>
</view>
</view>
</view>
<!-- 分页组件 -->
<uni-pagination
v-if="total > 0"
:total="total"
:pageSize="pagination.pageSize"
:current="pagination.pageNum"
@change="onPageChange"
mode="number"
show-icon
style="margin: 20px auto;"
></uni-pagination>
</view>
</template>
<script>
import { listProfit } from '@/api/oa/finance/profit';
export default {
props: {
// 接收从父组件传递的筛选参数
filterParams: {
type: Object,
default: () => ({})
}
},
data() {
return {
loading: false,
profitList: [],
total: 0,
// 分页参数
pagination: {
pageNum: 1,
pageSize: 10
},
// 盈亏阈值配置
profitThresholds: {
highProfit: 100000, // 高盈利阈值
highLoss: -50000, // 高亏损阈值
warningProfit: 50000, // 警告盈利阈值
warningLoss: -20000 // 警告亏损阈值
},
// 贸易类型字典
tradeTypeDict: [
{ value: 1, label: '外贸' },
{ value: 0, label: '内贸' },
]
};
},
watch: {
// 监听筛选参数变化,重新加载数据
filterParams: {
deep: true,
handler() {
// 筛选条件变化时重置页码
this.pagination.pageNum = 1;
this.getList();
}
}
},
methods: {
// 获取列表数据
getList() {
this.loading = true;
// 合并筛选参数和分页参数
const params = {
...this.filterParams,
...this.pagination
};
listProfit(params)
.then((res) => {
this.profitList = res.rows || [];
this.total = res.total || 0;
this.loading = false;
})
.catch(() => {
this.loading = false;
uni.showToast({
title: '加载失败',
icon: 'none',
});
});
},
// 分页变化
onPageChange(e) {
this.pagination.pageNum = e.current;
this.pagination.pageSize = e.size;
this.getList();
},
// 盈亏相关计算
getProfitRate(row) {
// 计算盈亏百分比
const base = row.originalFunds && row.originalFunds !== 0
? row.originalFunds
: row.detailIncome;
if (!base || base === 0) return null;
return row.profitLoss / base;
},
getProfitRateTag(row) {
const rate = this.getProfitRate(row);
if (rate === null) return '-';
if (rate >= 0.2) return '高盈利';
if (rate <= -0.2) return '高亏损';
if (rate < 0) return '亏损';
if (rate >= 0 && rate <= 0.05) return '低盈利';
return '盈利';
},
getProfitRateType(row) {
const rate = this.getProfitRate(row);
if (rate === null) return 'default';
if (rate >= 0.2) return 'success';
if (rate <= -0.2) return 'error';
if (rate < 0) return 'warning';
return rate >= 0 && rate <= 0.05 ? 'info' : 'success';
},
getProfitLossStyle(row) {
const rate = this.getProfitRate(row);
if (rate === null) return {};
if (rate >= 0.2) {
return {
color: '#67C23A',
fontWeight: 'bold',
};
} else if (rate <= -0.2) {
return {
color: '#F56C6C',
fontWeight: 'bold',
};
} else if (rate < 0) {
return {
color: '#F56C6C',
};
} else if (rate >= 0 && rate <= 0.05) {
return {
color: '#E6A23C',
};
} else {
return { color: '#67C23A' };
}
},
// 获取贸易类型名称
getTradeTypeName(value) {
const item = this.tradeTypeDict.find(item => item.value === value);
return item ? item.label : value;
}
},
// 组件挂载时加载数据
mounted() {
this.getList();
}
};
</script>
<style scoped>
.container {
flex: 1;
flex-direction: column;
background-color: #f5f5f5;
min-height: 100vh;
}
/* 列表样式 */
.list-container {
padding: 10px;
}
.project-card {
background-color: #fff;
border-radius: 8px;
padding: 15px;
margin-bottom: 10px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 10px;
}
.header-left {
flex: 1;
}
.project-name {
font-size: 16px;
font-weight: bold;
display: block;
margin-bottom: 5px;
color: #333;
}
.project-num {
font-size: 12px;
color: #666;
}
.card-body {
margin-bottom: 10px;
}
.info-row {
display: flex;
margin-bottom: 8px;
font-size: 14px;
}
.info-label {
color: #666;
width: 80px;
flex-shrink: 0;
}
.info-value {
flex: 1;
color: #333;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
padding-top: 10px;
border-top: 1px dashed #eee;
}
.profit-info {
display: flex;
align-items: center;
}
.profit-label {
color: #666;
margin-right: 5px;
}
.profit-value {
font-weight: bold;
}
/* 空状态 */
.empty-view {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 50px 0;
}
.empty-text {
color: #999;
margin-top: 10px;
font-size: 14px;
}
/* 解决uni组件样式冲突 */
::v-deep .uni-tag {
margin-top: 2px;
}
::v-deep .uni-pagination {
text-align: center;
}
</style>