Files
im-uniapp/pages/workbench/profit/profit.vue
2025-08-20 13:44:05 +08:00

489 lines
10 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="">
<view class="">
<!-- 查询条件 -->
</view>
<uni-icons></uni-icons>
</view>
<view class="">
<!-- 排序规则 -->
</view>
<!-- 列表内容区域 -->
<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>
</view>
</template>
<script>
import { listProfit } from '@/api/oa/finance/profit';
export default {
data() {
return {
loading: false,
profitList: [],
total: 0,
showFilter: false,
showSort: false,
showColumns: false,
dateRangeText: '',
// 盈亏阈值配置
profitThresholds: {
highProfit: 100000, // 高盈利阈值
highLoss: -50000, // 高亏损阈值
warningProfit: 50000, // 警告盈利阈值
warningLoss: -20000 // 警告亏损阈值
},
queryParams: {
projectName: '',
projectNum: '',
projectStatus: '',
isDomestic: '',
minContractAmount: '',
maxContractAmount: '',
minProfitLoss: '',
maxProfitLoss: '',
beginTimeStart: '',
beginTimeEnd: '',
profitType: '',
sortField: '',
sortOrder: 'desc',
pageNum: 1,
pageSize: 9999,
projectCode: '',
tradeType: '',
},
// 贸易类型字典
tradeTypeDict: [
{ value: 1, label: '外贸' },
{ value: 0, label: '内贸' },
]
};
},
onLoad() {
this.getList();
},
methods: {
getList() {
this.loading = true;
listProfit(this.queryParams).then(res => {
this.profitList = res.rows || [];
this.total = res.total || 0;
this.loading = false;
}).catch(() => {
this.loading = false;
uni.showToast({
title: '加载失败',
icon: 'none'
});
});
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
// 筛选相关方法
onDateChange(e) {
if (e.length === 2) {
this.queryParams.beginTimeStart = e[0];
this.queryParams.beginTimeEnd = e[1];
this.dateRangeText = `${e[0]} - ${e[1]}`;
} else {
this.queryParams.beginTimeStart = '';
this.queryParams.beginTimeEnd = '';
this.dateRangeText = '';
}
},
resetFilter() {
this.queryParams = {
...this.queryParams,
projectName: '',
projectNum: '',
projectStatus: '',
profitType: '',
beginTimeStart: '',
beginTimeEnd: '',
tradeType: ''
};
this.dateRangeText = '';
},
confirmFilter() {
this.showFilter = false;
this.handleQuery();
},
// 排序相关方法
setSort(field) {
this.queryParams.sortField = field;
this.handleQuery();
},
// 列显示控制
handleColumnChange() {
// 无需额外操作,数据驱动视图
},
// 分页相关
onPageChange(e) {
this.queryParams.pageNum = e.current;
this.queryParams.pageSize = e.pageSize;
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;
}
}
};
</script>
<style scoped>
.container {
flex: 1;
flex-direction: column;
background-color: #f5f5f5;
min-height: 100vh;
}
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
height: 44px;
background-color: #007aff;
padding: 0 15px;
}
.title {
color: #fff;
font-size: 18px;
font-weight: bold;
}
.right-ops {
display: flex;
}
.btn-icon {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: none;
padding: 0;
margin-left: 5px;
}
/* 弹窗样式 */
.popup-title {
padding: 15px;
font-size: 16px;
font-weight: bold;
border-bottom: 1px solid #eee;
}
.popup-content {
padding: 15px;
height: calc(100% - 120px);
}
.form-item {
margin-bottom: 15px;
display: flex;
flex-direction: column;
}
.form-label {
font-size: 14px;
color: #666;
margin-bottom: 5px;
}
.popup-btns {
display: flex;
padding: 10px;
border-top: 1px solid #eee;
}
.btn-reset, .btn-confirm {
flex: 1;
height: 40px;
line-height: 40px;
border-radius: 6px;
font-size: 16px;
}
.btn-reset {
background-color: #f5f5f5;
color: #333;
margin-right: 10px;
}
.btn-confirm {
background-color: #007aff;
color: #fff;
}
/* 排序弹窗样式 */
.sort-item {
padding: 15px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #eee;
}
.sort-direction {
padding: 15px;
display: flex;
align-items: center;
}
.direction-btn {
margin-left: 10px;
padding: 5px 10px;
border-radius: 4px;
font-size: 14px;
}
.direction-btn.active {
background-color: #007aff;
color: #fff;
}
/* 列设置弹窗 */
.column-item {
padding: 15px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #eee;
}
/* 列表样式 */
.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;
}
.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;
}
.info-value {
flex: 1;
}
.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;
}
</style>