Files
intc-vue-h5/src/pages/statistic/accounts/accountDealAnalysis/index.vue
2025-11-13 00:01:38 +08:00

551 lines
17 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">
<u-sticky offsetTop="8rpx" customNavHeight="8rpx">
<view class="search-view">
<u-input v-model="queryParams.time" border="false" type="select" placeholder="" suffixIcon="calendar"
suffixIconStyle="color: #909399" class="search-input">
</u-input>
<u-icon :name="filterPanel ? 'arrow-up-fill' : 'arrow-down-fill'" color="#666666" size="28" label="筛选"
labelPos="left" labelSize="32rpx" labelColor="#666666" @click="filterPanel = !filterPanel"></u-icon>
<u-transition :show="filterPanel" mode="fade">
<view class="filter-panel" :style="{ height: `${windowHeight - 42}px` }">
<view class="filter-panel-content">
<view class="select-header">交易日期</view>
<view class="selcet-content" style="padding: 0 24rpx">
<u-input
:disabled="true"
:disabledColor="'#fff'"
class="dateInput"
border="surround"
v-model="queryParams.startTime"
placeholder="请选择开始时间"
>
<template v-slot:suffix>
<u-icon name="calendar" @click="openOrCloseDate(true)"></u-icon>
</template>
</u-input>
<u-input
:disabled="true"
:disabledColor="'#fff'"
class="dateInput"
border="surround"
v-model="queryParams.endTime"
placeholder="请选择结束时间"
>
<template v-slot:suffix>
<u-icon name="calendar" @click="openOrCloseDate(false)"></u-icon>
</template>
</u-input>
</view>
</view>
<view class="btn-box">
<u-button text="重置" style="margin-right:20rpx" @click="resetQuery()"></u-button>
<u-button type="primary" text="确定" @click="searchSubmit()"></u-button>
</view>
<u-datetime-picker
:closeOnClickOverlay="true"
:show="timeShow"
v-model="time"
mode="date"
:minDate="-2209017600000"
@close="openOrCloseDate"
@cancel="openOrCloseDate"
@confirm="confirm"
></u-datetime-picker>
</view>
</u-transition>
</view>
</u-sticky>
<div class="app-container">
<div class="header-con" ref="searchHeightRef">
<div class="item">
<view class="item-icon" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
<uni-icons type="wallet" size="20" color="#ffffff"></uni-icons>
</view>
<div class="info-sum">
<div class="title">收支差额</div>
<div class="num">{{ account.balance }}<span></span></div>
</div>
</div>
<div class="item">
<view class="item-icon" style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">
<uni-icons type="star-filled" size="20" color="#ffffff"></uni-icons>
</view>
<div class="info-sum">
<div class="title">工资收益</div>
<div class="num">{{ account.salaryIncome }}<span></span></div>
</div>
</div>
</div>
<div class="header-con" v-show="auth.hasPermi('invest:futureStocks:list')" ref="searchHeightRef">
<div class="item">
<view class="item-icon" style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);">
<uni-icons type="arrow-up" size="20" color="#ffffff"></uni-icons>
</view>
<div class="info-sum">
<div class="title">投资盈利</div>
<div class="num">{{ account.investIncome}}<span></span></div>
</div>
</div>
<div class="item">
<view class="item-icon" style="background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);">
<uni-icons type="arrow-down" size="20" color="#ffffff"></uni-icons>
</view>
<div class="info-sum">
<div class="title">投资亏损</div>
<div class="num">{{ account.investOutcome }}<span></span></div>
</div>
</div>
</div>
<div class="header-con" ref="searchHeightRef">
<div class="item">
<view class="item-icon" style="background: linear-gradient(135deg, #fa709a 0%, #fee140 100%);">
<uni-icons type="list" size="20" color="#ffffff"></uni-icons>
</view>
<div class="info-sum">
<div class="title">支出总额</div>
<div class="num">{{ account.totalOutcome}}<span></span></div>
</div>
</div>
<div class="item">
<view class="item-icon" style="background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);">
<uni-icons type="wallet-filled" size="20" color="#ffffff"></uni-icons>
</view>
<div class="info-sum">
<div class="title">日常支出</div>
<div class="num">{{ account.dailyExpenses }}<span></span></div>
</div>
</div>
</div>
<div class="header-con" v-show="auth.hasPermi('invest:creditCard','invest:posmachine:list','invest:onlineLend')" ref="searchHeightRef">
<div class="item" v-show="auth.hasPermi('invest:creditCard','invest:posmachine:list','invest:onlineLend')">
<view class="item-icon" style="background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);">
<uni-icons type="calendar-filled" size="20" color="#ffffff"></uni-icons>
</view>
<div class="info-sum">
<div class="title">手续费利息合计</div>
<div class="num">{{ account.notDailyExpenses}}<span></span></div>
</div>
</div>
<div class="item" v-show="auth.hasPermi('invest:creditCard')">
<view class="item-icon" style="background: linear-gradient(135deg, #fddb92 0%, #d1fdff 100%);">
<uni-icons type="star" size="20" color="#ffffff"></uni-icons>
</view>
<div class="info-sum">
<div class="title">信用卡分期利息</div>
<div class="num">{{ account.creditInterest}}<span></span></div>
</div>
</div>
</div>
<div class="header-con" v-show="auth.hasPermi('invest:posmachine:list','invest:onlineLend')" ref="searchHeightRef">
<div class="item" v-show="auth.hasPermi('invest:posmachine:list')">
<view class="item-icon" style="background: linear-gradient(135deg, #89f7fe 0%, #66a6ff 100%);">
<uni-icons type="shop-filled" size="20" color="#ffffff"></uni-icons>
</view>
<div class="info-sum">
<div class="title">POS机手续费</div>
<div class="num">{{ account.posExpenses }}<span></span></div>
</div>
</div>
<div class="item" v-show="auth.hasPermi('invest:onlineLend')">
<view class="item-icon" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
<uni-icons type="upload-filled" size="20" color="#ffffff"></uni-icons>
</view>
<div class="info-sum">
<div class="title">贷款利息</div>
<div class="num">{{ account.onLineInterest }}<span></span></div>
</div>
</div>
</div>
<div></div>
</div>
<div style="margin:8px" v-show="listData.length>0">
<button type="primary" style="margin-right:5px" size=mini>账户收支统计</button>
</div>
<u-list :spaceHeight="116" lowerThreshold="100">
<u-list-item v-for="(item, index) in listData" :key="index">
<view class="list-item">
<view class="item-header">
<u--text lines="2"
:text="item.time+' 收支金额:'+item.value" size="30rpx" color="#333333" ></u--text>
</view>
<view class="item-row">
<text class="row-label">收支明细</text><br>
<text class="row-value">{{ formatMultiLineData(item.detail)}}</text>
</view>
</view>
</u-list-item>
<view>
</view>
</u-list>
</view>
<!-- 悬停按钮返回工作台-->
<suspend></suspend>
<refresh></refresh>
</template>
<script setup>
import { getAcccountsOutInAnalysis } from '@/api/invest/statisticAnalysis'
import dayjs from 'dayjs'
import { timeHandler } from '@/utils/common.ts'
import auth from "@/plugins/auth"; // 建议使用auth进行鉴权操作
import { listAccounts } from '@/api/invest/accounts'
import {onLoad,onShow} from "@dcloudio/uni-app";
// 计算属性与监听属性是在vue中而非uniap中 需要注意!!!
import {reactive ,toRefs,ref,computed }from "vue";
const pageNum = ref(1)
const listData = ref([])
const isShow = ref(false)
const accountList = ref([])
const timeShow= ref(false)
const time =ref( Number(new Date()))
const flag= ref(true)
const account = ref({
amount: '',
income: '',
expenses: '',
incomeCount: '',
expensesCount: '',
posExpensesCount: '',
posExpenses: '',
realExpenses: '',
realExpensesCount: '',
otherExpensesCount: '',
acccountsList: []
})
const data = reactive({
filterPanel: false,
queryAccountParams: {
pageNum: 1,
state: '1',
pageSize: 100
},
queryParams: {
type: 1,
time: null,
id: null
}
})
const { filterPanel, queryAccountParams, queryParams} = toRefs(data)
const windowHeight = computed(() => {
uni.getSystemInfoSync().windowHeight - 50
})
onLoad(() => {
getDict()
getList()
});
onShow(() => {
if (isShow.value) {
listData.value=[]
getList()
isShow.value = false
}
});
function formatMultiLineData(data) {
if (data != null) {
return data.replace(/<br\/>/g, '\n')
}
}
function openOrCloseDate(data) {
timeShow.value = !timeShow.value
flag.value = data
}
function confirm(e) {
const date = timeHandler(new Date(e.value), '-', ':')
let formatValue = 'YYYY-MM-DD'
dayjs(date).format(formatValue)
if (flag.value) {
queryParams.value.startTime = dayjs(date).format(formatValue)
} else {
queryParams.value.endTime = dayjs(date).format(formatValue)
}
timeShow.value = false
}
function searchSubmit() {
queryParams.value.time = queryParams.value.startTime+'-'+queryParams.value.endTime
pageNum.value = 1
listData.value = []
getList()
filterPanel.value = false
}
function resetQuery() {
queryParams.value.id = ''
queryParams.value.type = '1'
let formatValue = 'YYYY-MM-DD'
const today = new Date()
const end = today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2) + '-' + ('0' + today.getDate()).slice(-2)
const start = dayjs(end).add(-7, 'day')
queryParams.value.time = dayjs(start).format(formatValue)+'-'+dayjs(end).format(formatValue)
queryParams.value.startTime = dayjs(start).format(formatValue)
queryParams.value.endTime = dayjs(end).format(formatValue)
}
function getList() {
getAcccountsOutInAnalysis({...queryParams.value }).then(res => {
account.value = { ...res.data }
listData.value = listData.value.concat(res.data.tableAccountsList)
}).catch(() => {
})
}
function getDict() {
let formatValue = 'YYYY-MM-DD'
const today = new Date()
const end = today.getFullYear() + '-' + ('0' + (today.getMonth() + 1)).slice(-2) + '-' + ('0' + today.getDate()).slice(-2)
const start = dayjs(end).add(-7, 'day')
queryParams.value.startTime = dayjs(start).format(formatValue)
queryParams.value.endTime = dayjs(end).format(formatValue)
queryParams.value.time = dayjs(start).format(formatValue)+'-'+dayjs(end).format(formatValue)
listAccounts(queryAccountParams.value).then((response) => {
accountList.value = [response.rows]
})
}
</script>
<style lang="scss" scoped>
.app-container {
background-color: #f5f7fa;
padding: 0;
overflow: visible;
.header-con {
width: calc(100% - 32rpx);
margin: 0 16rpx 8rpx 16rpx;
background-color: transparent;
display: flex;
justify-content: space-between;
align-items: stretch;
padding: 0;
gap: 12rpx;
.item {
flex: 1;
display: flex;
align-items: center;
padding: 20rpx 16rpx;
transition: all 0.3s ease;
border: 2rpx solid #e8edf3;
border-radius: 16rpx;
background: linear-gradient(135deg, #ffffff 0%, #f8f9fb 100%);
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
&:active {
transform: scale(0.98);
opacity: 0.9;
}
.item-icon {
width: 72rpx;
height: 72rpx;
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 16rpx;
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
flex-shrink: 0;
}
.info-sum {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
.title {
color: #7f8c8d;
margin-bottom: 8rpx;
font-size: 24rpx;
}
.num {
color: #2c3e50;
font-size: 32rpx;
font-weight: 600;
span {
font-size: 20rpx;
color: #95a5a6;
margin-left: 4rpx;
}
}
}
}
}
}
.btnAdd {
width: 146rpx;
height: 56rpx;
line-height: 56rpx;
border-radius: 8rpx;
display:float;
text-align: center;
}
.search-view {
padding: 12rpx 32rpx;
background-color: #ffffff;
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
.search-input {
background: #F5F5F5;
color: #333333;
margin-right: 36rpx;
}
.filter-panel {
width: 100%;
position: absolute;
left: 0;
top: 96rpx;
background-color: rgba(0, 0, 0, 0.5);
.filter-panel-content {
background-color: #ffff;
padding: 0 30rpx 30rpx;
.filter-title {
color: #000000;
font-size: 30rpx;
font-weight: 500;
padding: 30rpx 0;
}
.state-list {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
.state-item {
width: 210rpx;
height: 72rpx;
border: 1rpx solid rgba(0, 0, 0, 0.25);
border-radius: 72rpx;
text-align: center;
line-height: 72rpx;
margin: 0 20rpx 20rpx 0;
font-size: 28rpx;
color: #000000;
}
.active {
background-color: rgba(222, 241, 255, 1);
border: 1rpx solid rgba(22, 119, 255, 1);
}
}
}
.btn-box {
display: flex;
padding: 24rpx 30rpx;
background-color: #fff;
box-shadow: 0rpx -10rpx 20rpx #EEEEEE;
}
}
}
.list-item {
margin: 0 24rpx 24rpx;
padding: 32rpx;
background-color: #fff;
.item-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 16rpx;
.status {
.status-item {
width: 120rpx;
height: 44rpx;
text-align: center;
line-height: 44rpx;
border-radius: 4rpx;
font-size: 24rpx;
}
.status1 {
background: #F0F0F0;
color: #8C8C8C;
}
.status2 {
background: rgba(38, 129, 255, 0.2);
color: #2681FF;
}
.status3 {
background: #F7F7F7;
color: #2681FF;
}
.status4 {
background: rgba(255, 85, 51, 0.2);
color: #FF5533;
}
.status5 {
background: #F7F7F7;
color: rgba(0, 0, 0, 0.85);
}
.status7 {
background: rgba(255, 129, 51, 0.2);
color: #FF8133;
}
.status8 {
background: rgba(65, 217, 165, 0.2);
color: #41D9A5;
}
}
}
.item-row {
padding: 16rpx 0;
.row-label {
color: rgba(0, 0, 0, 0.55);
}
.row-value {
color: rgba(0, 0, 0, 0.85)
}
}
.operate {
display: flex;
justify-content: flex-end;
.btn {
width: 146rpx;
height: 56rpx;
line-height: 56rpx;
border-radius: 8rpx;
margin-left: 5rpx;
text-align: center;
}
.circulation {
background: rgba(0, 0, 0, 0.04);
margin-right: 24rpx;
color: rgba(0, 0, 0, 0.85);
}
.filling {
background: #2681FF;
border-radius: 8rpx;
color: #FFFFFF;
}
}
}
</style>