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.
490 lines
20 KiB
490 lines
20 KiB
<template>
|
|
<div class="main-content12 expense-wrap">
|
|
<h3 class="pagetitle">收支统计</h3>
|
|
<div class="flex-common">
|
|
<div class="flex-between">
|
|
<el-tabs v-model="totalType" @tab-click="handleClick">
|
|
<el-tab-pane label="月统计列表" name="1"></el-tab-pane>
|
|
<el-tab-pane v-if="siteNum>1" label="各站点统计列表" name="2"></el-tab-pane>
|
|
<el-tab-pane label="各服务统计列表" name="3"></el-tab-pane>
|
|
</el-tabs>
|
|
<div class="flex">
|
|
<!-- <GuipSelect label="服务类型" v-if="totalType == '3'" :options="[{label:'asd',value:'9'}]"></GuipSelect>-->
|
|
<!-- <GuipSelect label="时间" :options="[{label:'asd',value:'9'}]"></GuipSelect>-->
|
|
<CustomDropdown ref="dropdownRef" :placeholder="date" width="280px">
|
|
<DateSelect slot="normal" view="month" :onlyMonth="true" @change="handleDateChange"/>
|
|
</CustomDropdown>
|
|
</div>
|
|
</div>
|
|
<div v-if="totalType == '1' && Object.keys(monthTotal).length>0" class="mt24 monthTotal-wrap flex">
|
|
<div class="total-item" :class="monthTotal.profit<0?'loss':''">
|
|
<div class="flex-between total-top">
|
|
<div class="top-left">
|
|
<img src="" alt="">
|
|
<b>月利润</b>
|
|
</div>
|
|
<span v-if="monthTotal.profit<0" class="loss-tip">亏损</span>
|
|
</div>
|
|
<div class="price">
|
|
<b>{{monthTotal.profit}}</b>元
|
|
</div>
|
|
<div class="gap24 flex-between total-bottom">
|
|
<div class="left column gap8">
|
|
<template v-for="(col, index) in payList">
|
|
<span v-if="index % 2 === 1" :key="index">{{ col.name }}:{{ monthTotal.pay_type[col.id].profit }}元</span>
|
|
</template>
|
|
</div>
|
|
<div class="right column gap8">
|
|
<template v-for="(col, index) in payList">
|
|
<span v-if="index % 2 === 0" :key="index">{{ col.name }}:{{ monthTotal.pay_type[col.id].profit }}元</span>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="total-item">
|
|
<div class="flex-between total-top">
|
|
<div class="top-left">
|
|
<img src="" alt="">
|
|
<b>月收入</b>
|
|
</div>
|
|
<span class="loss-tip-empty"></span>
|
|
</div>
|
|
<div class="price">
|
|
<b>{{this.monthTotal.income}}</b>元
|
|
</div>
|
|
<div class="gap24 flex-between total-bottom">
|
|
<div class="left column gap8">
|
|
<template v-for="(col, index) in payList">
|
|
<span v-if="index % 2 === 1" :key="index">{{ col.name }}:{{ monthTotal.pay_type[col.id].income }}元</span>
|
|
</template>
|
|
</div>
|
|
<div class="right column gap8">
|
|
<template v-for="(col, index) in payList">
|
|
<span v-if="index % 2 === 0" :key="index">{{ col.name }}:{{ monthTotal.pay_type[col.id].income }}元</span>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="total-item">
|
|
<div class="flex-between total-top">
|
|
<div class="top-left">
|
|
<img src="" alt="">
|
|
<b>月支出</b>
|
|
</div>
|
|
<span class="loss-tip-empty"></span>
|
|
</div>
|
|
<div class="price">
|
|
<b>{{this.monthTotal.cost}}</b>元
|
|
</div>
|
|
<div class="gap24 flex-between total-bottom">
|
|
<div class="left column gap8">
|
|
<template v-for="(col, index) in payList">
|
|
<span v-if="index % 2 === 1" :key="index">{{ col.name }}:{{ monthTotal.pay_type[col.id].cost }}元</span>
|
|
</template>
|
|
</div>
|
|
<div class="right column gap8">
|
|
<template v-for="(col, index) in payList">
|
|
<span v-if="index % 2 === 0" :key="index">{{ col.name }}:{{ monthTotal.pay_type[col.id].cost }}元</span>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="total-item">
|
|
<div class="flex-between total-top">
|
|
<div class="top-left">
|
|
<img src="" alt="">
|
|
<b>月单量</b>
|
|
</div>
|
|
<span class="loss-tip-empty"></span>
|
|
</div>
|
|
<div class="price">
|
|
<b>{{this.monthTotal.check_num}}</b>元
|
|
</div>
|
|
<div class="gap24 flex-between total-bottom">
|
|
<div class="left column gap8">
|
|
<template v-for="(col, index) in payList">
|
|
<span v-if="index % 2 === 1" :key="index">{{ col.name }}:{{ monthTotal.pay_type[col.id].check_num }}单</span>
|
|
</template>
|
|
</div>
|
|
<div class="right column gap8">
|
|
<template v-for="(col, index) in payList">
|
|
<span v-if="index % 2 === 0" :key="index">{{ col.name }}:{{ monthTotal.pay_type[col.id].check_num }}单</span>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<el-form class="mt24">
|
|
<GuipTable :tableData="monthList" :key="tableKey" ref="multipleTable" autoColumn="true" :loading="tableLoading" style="flex:1"
|
|
:show-summary="totalType === '1'"
|
|
:summary-method="totalType === '1' ? getSummaries : null">
|
|
<el-table-column prop="date" label="日期" min-width="130px" v-if="totalType == '1'"></el-table-column>
|
|
<el-table-column prop="date1" label="站点名称" min-width="130px" v-if="totalType == '2'">
|
|
<template slot-scope="scope">
|
|
<div class="flex">
|
|
{{ nameList[scope.row.id] }}
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="date2" label="服务名称" min-width="130px" v-if="totalType == '3'">
|
|
<template slot-scope="scope">
|
|
<div class="flex">
|
|
{{ nameList[scope.row.id] }}
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="profit" label="利润" min-width="110px">
|
|
<template slot-scope="scope">
|
|
<div class="flex" :class="scope.row.profit<0?'red':''">
|
|
{{ scope.row.profit ? scope.row.profit : '-' }}
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="income" label="收入" min-width="110px">
|
|
<template slot-scope="scope">
|
|
<div class="flex">
|
|
{{ scope.row.income ? scope.row.income : '-' }}
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="expenditure" label="支出" min-width="110px">
|
|
<template slot-scope="scope">
|
|
<div class="flex">
|
|
{{ scope.row.cost ? scope.row.cost : '-' }}
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="orderVolume" label="单量" min-width="110px">
|
|
<template slot-scope="scope">
|
|
<div class="flex">
|
|
{{ scope.row.check_num ? scope.row.check_num : '-' }}
|
|
</div>
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column v-for="(col, index) in payList" :key="index" :label="col.name+'收/支/单量'" min-width="160px">
|
|
<template slot-scope="scope">
|
|
<div class="flex" v-if="scope.row.pay_type[col.id]">
|
|
{{ scope.row.pay_type[col.id].income }}/
|
|
{{ scope.row.pay_type[col.id].cost }}/
|
|
{{ scope.row.pay_type[col.id].check_num }}
|
|
</div>
|
|
<div v-else>-</div>
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column v-if="totalType == '3'"
|
|
key="top1" prop="top1" label="站点排行(利润)" width="250">
|
|
<template slot-scope="scope">
|
|
<span v-if="topList[scope.row.id]" slot="reference" class="flex">
|
|
NO.1 {{topList[scope.row.id]}}
|
|
<svg-icon :size="14" @click="handleClicksiteRank(scope.row.id)"
|
|
:path="require('@/assets/super/list-detail.svg')" :color="'#8A9099'"
|
|
:hoverColor="'#006AFF'" />
|
|
</span>
|
|
<span v-else slot="reference">暂无排行</span>
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column v-if="totalType == '2'"
|
|
key="top2" prop="top2" label="服务排行(利润)" width="250">
|
|
<template slot-scope="scope">
|
|
<span v-if="topList[scope.row.id]" slot="reference" class="flex">
|
|
NO.1 {{topList[scope.row.id]}}
|
|
<svg-icon :size="14" @click="handleClickserviceRank(scope.row.id)"
|
|
:path="require('@/assets/super/list-detail.svg')" :color="'#8A9099'"
|
|
:hoverColor="'#006AFF'" />
|
|
</span>
|
|
<span v-else slot="reference">暂无排行</span>
|
|
</template>
|
|
</el-table-column>
|
|
|
|
<el-table-column label="操作" fixed="right" v-if="totalType != '1'">
|
|
<template slot-scope="scope">
|
|
<GuipButton type="text" class="mr-16" @click="handleClickDetail(scope.row.id)">详情</GuipButton>
|
|
</template>
|
|
</el-table-column>
|
|
</GuipTable>
|
|
</el-form>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script>
|
|
import GuipButton from '@/components/GuipButton.vue';
|
|
// import GuipSelect from '@/components/GuipSelect.vue';
|
|
import GuipTable from '@/components/GuipTable.vue';
|
|
import SvgIcon from '@/components/SvgIcon.vue';
|
|
import DateSelect from "@/components/super/DateSelect.vue";
|
|
import CustomDropdown from "@/components/CustomDropdown.vue";
|
|
|
|
export default {
|
|
components: {
|
|
CustomDropdown, DateSelect,
|
|
GuipTable,
|
|
GuipButton,
|
|
// GuipSelect,
|
|
SvgIcon
|
|
},
|
|
props: {
|
|
total_type: {
|
|
type: String,
|
|
default: '1'
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
totalType:'1',
|
|
date: this.getNow(),
|
|
tableLoading:false,
|
|
siteNum: 1,
|
|
tableKey: '',
|
|
monthList:[],
|
|
monthTotal:[],
|
|
payList:[],
|
|
nameList:[],
|
|
topList:[],
|
|
}
|
|
},
|
|
mounted() {
|
|
const {total_type, date} = this.$route.query
|
|
this.$nextTick(()=>{
|
|
this.totalType = this.total_type;
|
|
if(total_type)this.totalType = total_type;
|
|
if(date) this.date = date;
|
|
|
|
this.getSiteNum()
|
|
this.handleClick()
|
|
})
|
|
},
|
|
methods: {
|
|
getNow() {
|
|
const now = new Date();
|
|
const year = now.getFullYear();
|
|
const month = now.getMonth() + 1;
|
|
return `${year}-${month}`
|
|
},
|
|
getDate(dateStr) {
|
|
const date = new Date(dateStr);
|
|
const year = date.getFullYear(); // 2025
|
|
const month = date.getMonth() + 1; // 3 (表示3月)
|
|
|
|
return `${year}-${month}`
|
|
},
|
|
handleDateChange(date) {
|
|
this.date = this.getDate(date)
|
|
localStorage.setItem('date', JSON.stringify(date))
|
|
|
|
this.$refs.dropdownRef.closeDropdown();
|
|
this.handleClick()
|
|
},
|
|
handleClickDetail(id){
|
|
if(this.totalType == 2) this.$router.push(`/agent/statisticalDetails?uid=${id}&total_type=${this.totalType}&date=${this.date}`)
|
|
if(this.totalType == 3) this.$router.push(`/agent/statisticalDetails?chktype=${id}&total_type=${this.totalType}&date=${this.date}`)
|
|
},
|
|
handleClicksiteRank(id){
|
|
this.$router.push(`/agent/siteRank?id=${id}&total_type=${this.totalType}&date=`+this.date)
|
|
},
|
|
handleClickserviceRank(id){
|
|
this.$router.push(`/agent/serviceRank?id=${id}&total_type=${this.totalType}&date=`+this.date)
|
|
},
|
|
handleClick(){
|
|
this.monthList = []
|
|
this.payList = []
|
|
this.monthTotal = []
|
|
this.nameList = []
|
|
this.topList = []
|
|
this.tableKey = Math.random();
|
|
if(this.totalType == 1) this.getDayStats()
|
|
if(this.totalType == 2) this.getSiteStats()
|
|
if(this.totalType == 3) this.getChktypeStats()
|
|
},
|
|
getSummaries() {
|
|
if(this.totalType != '1') return []
|
|
const sums = [];
|
|
|
|
let index = 0
|
|
sums[index] = `小计`
|
|
sums[++index] = this.monthTotal.profit
|
|
sums[++index] = this.monthTotal.income
|
|
sums[++index] = this.monthTotal.cost
|
|
sums[++index] = this.monthTotal.check_num
|
|
this.payList.forEach(column =>{
|
|
sums[++index] = this.monthTotal.pay_type[column.id].income + '/' + this.monthTotal.pay_type[column.id].cost + '/' + this.monthTotal.pay_type[column.id].check_num
|
|
})
|
|
|
|
return sums;
|
|
},
|
|
getSiteNum() {
|
|
try {
|
|
this.$http('POST', '/agentnew/ajax_get_agent_sitenum', {date: this.date}).then(response => {
|
|
this.$nextTick(() => {
|
|
this.siteNum = response.data
|
|
})
|
|
}).catch(error => {
|
|
console.error(error, 'error')
|
|
})
|
|
} catch (error) {
|
|
console.error('数据加载失败:', error)
|
|
}
|
|
},
|
|
getDayStats() {
|
|
this.tableLoading = true
|
|
try {
|
|
this.$http('POST', '/agentnew/ajax_get_day_stats', {date: this.date}).then(response => {
|
|
this.$nextTick(() => {
|
|
this.monthList = response.data.list
|
|
this.payList = response.data.pay_list
|
|
this.monthTotal = response.data.total
|
|
})
|
|
}).catch(error => {
|
|
console.error(error, 'error')
|
|
})
|
|
} catch (error) {
|
|
console.error('数据加载失败:', error)
|
|
} finally {
|
|
this.tableLoading = false
|
|
}
|
|
},
|
|
getSiteStats() {
|
|
this.tableLoading = true
|
|
try {
|
|
this.$http('POST', '/agentnew/ajax_get_site_stats', {date: this.date}).then(response => {
|
|
this.tableLoading = false
|
|
this.$nextTick(() => {
|
|
this.monthList = response.data.list
|
|
this.payList = response.data.pay_list
|
|
this.monthTotal = response.data.total
|
|
this.nameList = response.data.name_list
|
|
this.topList = response.data.top_list
|
|
})
|
|
}).catch(error => {
|
|
console.error(error, 'error')
|
|
})
|
|
} catch (error) {
|
|
console.error('数据加载失败:', error)
|
|
} finally {
|
|
this.tableLoading = false
|
|
}
|
|
},
|
|
getChktypeStats() {
|
|
this.tableLoading = true
|
|
try {
|
|
this.$http('POST', '/agentnew/ajax_get_chktype_stats', {date: this.date}).then(response => {
|
|
this.tableLoading = false
|
|
this.$nextTick(() => {
|
|
this.monthList = response.data.list
|
|
this.payList = response.data.pay_list
|
|
this.monthTotal = response.data.total
|
|
this.nameList = response.data.name_list
|
|
this.topList = response.data.top_list
|
|
})
|
|
}).catch(error => {
|
|
console.error(error, 'error')
|
|
})
|
|
} catch (error) {
|
|
console.error('数据加载失败:', error)
|
|
} finally {
|
|
this.tableLoading = false
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
::v-deep .el-table__footer-wrapper tbody td.el-table__cell {
|
|
background-color: #E8F0FE; /* 背景色 */
|
|
color: #006AFF; /* 文字颜色 */
|
|
font-weight: 600;
|
|
}
|
|
|
|
.loss-profit{
|
|
color: #FF4D4F;
|
|
}
|
|
.red{
|
|
color: #FF4D4F;
|
|
}
|
|
|
|
.expense-wrap{
|
|
::v-deep .el-tabs__header{
|
|
margin: 0;
|
|
}
|
|
.pagetitle {
|
|
text-align: left;
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
line-height: normal;
|
|
letter-spacing: 0.08em;
|
|
color: #1E2226;
|
|
margin-top: 8px;
|
|
}
|
|
.monthTotal-wrap{
|
|
display: grid;
|
|
grid-gap: 12px;
|
|
grid-template-columns: repeat(auto-fit, 287px);
|
|
}
|
|
|
|
.loss-tip{
|
|
width: 50px;
|
|
height: 24px;
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
box-sizing: border-box;
|
|
border-radius: 4px;
|
|
background: #FFF1F0;
|
|
box-sizing: border-box;
|
|
border: 1px solid #FFA39E;
|
|
font-size: 14px;
|
|
font-weight: normal;
|
|
line-height: 20px;
|
|
text-align: center;
|
|
letter-spacing: 0.08em;
|
|
color: #FF4D4F;
|
|
}
|
|
.loss-tip-empty{
|
|
width: 50px;
|
|
height: 24px;
|
|
display: flex;
|
|
}
|
|
.total-item{
|
|
padding: 14px 16px;
|
|
font-size: 12px;
|
|
letter-spacing: 0.03em;
|
|
color: #23242B;
|
|
box-sizing: border-box;
|
|
border-radius: 4px;
|
|
background: #F2F7FF;
|
|
min-height: 153px;
|
|
.price{
|
|
text-align: left;
|
|
font-size: 12px;
|
|
font-weight: normal;
|
|
line-height: 15px;
|
|
letter-spacing: 0.08em;
|
|
color: #1E2226;
|
|
margin: 14px 0;
|
|
b{
|
|
font-size: 22px;
|
|
line-height: 20px;
|
|
letter-spacing: normal;
|
|
}
|
|
}
|
|
.total-bottom{
|
|
align-items: flex-start;
|
|
}
|
|
}
|
|
.loss{
|
|
background: #FFF1F0;
|
|
.top-left b{
|
|
color: #FF4D4F;
|
|
}
|
|
}
|
|
.gain{
|
|
background: #EFFFE0;
|
|
.top-left b{
|
|
color: #00C261;
|
|
}
|
|
}
|
|
}
|
|
</style>
|