master
lion 5 months ago
parent dab679f3a1
commit ca59d5fd50

@ -186,6 +186,7 @@ export default {
header-align={item.headerAlign ?? 'center'}
label={item.label}
prop={item.prop}
show-overflow-tooltip={true}
scopedSlots={{
default(scope) {
return item.customFn(scope.row, scope)
@ -210,6 +211,7 @@ export default {
width={item1.width ?? 'auto'}
min-width={item1.minWidth ?? item1.width}
sortable={item1.sortable ?? true}
show-overflow-tooltip={true}
scopedSlots={{
default(scope) {
return item1.customFn(scope.row, scope)
@ -228,6 +230,7 @@ export default {
width={item1.width ?? 'auto'}
min-width={item1.minWidth ?? item1.width}
sortable={item1.sortable ?? true}
show-overflow-tooltip={true}
type={item1.type ?? ''}
formatter={item1.formatter}>
</el-table-column>
@ -249,6 +252,7 @@ export default {
label={item.label}
prop={item.prop}
label-class-name={item.labelClassName}
show-overflow-tooltip={true}
sortable={item.sortable ?? true}
type={item.type}
reserve-selection={item.reserveSelection}

@ -67,7 +67,7 @@
<div class="xy-table-item-label" style="width: 200px">是否收取履约保函
</div>
<div class="xy-table-item-content">
<el-switch style="width: 300px" v-model="form.is_assurance" />
<el-switch active-text="" inactive-text="" style="width: 300px" v-model="form.is_assurance" />
</div>
</div>
</template>
@ -141,7 +141,7 @@
<template v-if="contract.is_contract===1" v-slot:other_tender_name>
<div class="xy-table-item">
<div class="xy-table-item-label">
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>其他投标单位
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>其他参与投标单位名称
</div>
<div class="xy-table-item-content ">
<el-button type="primary" style="margin-bottom:10px" size="small" @click="addRow"></el-button>
@ -166,8 +166,16 @@
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>事前询价情况
</div>
<div class="xy-table-item-content">
<el-input v-model="form.quotation_situation" type="textarea" placeholder="第三方造价咨询单位出具的报告或标底/供应商提供的报价"
style="width: 300px;" />
<el-select v-model="form.quotation_situation" placeholder="请选择" style="width:300px">
<el-option
v-for="(item,index) in ['第三方造价咨询单位出具的报告或标底','供应商提供的报价']"
:key="index"
:label="item"
:value="item">
</el-option>
</el-select>
<!-- <el-input v-model="form.quotation_situation" type="textarea" placeholder="第三方造价咨询单位出具的报告或标底/供应商提供的报价"
style="width: 300px;" /> -->
</div>
</div>
</template>
@ -177,8 +185,16 @@
<span style="color: red;font-weight: 600;padding-right: 4px;">*</span>事后审计情况
</div>
<div class="xy-table-item-content">
<el-input v-model="form.audit_situation" type="textarea" placeholder="外部财政局或审计局审计/内部自行委托的第三方审计/未审计。"
style="width: 300px;" />
<el-select v-model="form.audit_situation" placeholder="请选择" style="width:300px">
<el-option
v-for="(item,index) in ['外部财政局或审计局审计','内部自行委托的第三方审计','未审计']"
:key="index"
:label="item"
:value="item">
</el-option>
</el-select>
<!-- <el-input v-model="form.audit_situation" type="textarea" placeholder="外部财政局或审计局审计/内部自行委托的第三方审计/未审计。"
style="width: 300px;" /> -->
</div>
</div>
</template>
@ -621,7 +637,7 @@
console.log("other",this.form.other_tender_name)
if(this.contract.is_contract===1){
if(this.form.other_tender_name.length<1){
this.$Message.warning(`请添加其他投标单位`)
this.$Message.warning(`请添加其他参与投标单位名称`)
return
}
if(!this.form.quotation_situation){

@ -70,7 +70,7 @@
</div>
<div v-if='detail.is_contract===1'>
<div class="sign-info-item">
<div class="sign-info-item-title">其他投标单位</div>
<div class="sign-info-item-title">其他参与投标单位名称</div>
<div class="sign-info-item-content">
<div v-for="item in detail.other_tender_name">{{item}}</div>
</div>

@ -140,7 +140,7 @@
</div>
</template>
<template v-slot:act_date>
<!-- <template v-slot:act_date>
<div v-if="contract_category && contract_category.show_apply_money === 1 && (!hasPostPaymentForm || (hasPostPaymentForm && currentStep === 2))" class="xy-table-item">
<div class="xy-table-item-label">
<span v-if="contract_category && contract_category.required_act_date === 1" style="color: red;font-weight: 600;padding-right: 4px;">*</span>
@ -150,7 +150,7 @@
<el-date-picker v-model="paymentRegistrationForm.act_date" type="date" value-format="yyyy-MM-dd" style="width: 150px;" />
</div>
</div>
</template>
</template> -->
<template v-slot:applyMoney>
<div v-if="contract_category && contract_category.show_apply_money === 1 && (!hasPostPaymentForm || (hasPostPaymentForm && currentStep === 2))" class="xy-table-item">
@ -977,12 +977,12 @@ export default {
message: '必填'
}
],
act_date: [
{
required: this.contract_category.required_act_date === 1,
message: '必填'
}
]
// act_date: [
// {
// required: this.contract_category.required_act_date === 1,
// message: ''
// }
// ]
}
const res = await getFundLog({
contract_id: this.contract.id,

@ -4,32 +4,6 @@
<div slot="content" />
<slot>
<div class="selects">
<div>
<span style="padding: 0 6px;word-break: keep-all;">
合同分类
</span>
<Select v-model="select.contract_category" disabled placeholder="请选择合同分类" style="width:140px;" @on-change="handleCategoryChange">
<Option v-for="item in categoryOptions" :key="item.id" :value="item.id">{{ item.value || item.name }}</Option>
</Select>
</div>
<div>
<span style="padding: 0 6px;word-break: keep-all;">
事务类型
</span>
<Select v-model="select.work_type" multiple clearable placeholder="请选择事务类型" style="width:180px;" :max-tag-count="1" @on-change="handleTransactionTypeChange">
<Option v-for="item in transactionTypes" :key="item.id" :value="item.id">{{ item.value || item.name }}</Option>
</Select>
</div>
<div>
<span style="padding: 0 6px;word-break: keep-all;">
合同类型
</span>
<Select v-model="select.contract_type" multiple clearable placeholder="请选择合同类型" style="width:160px;" :max-tag-count="1" @on-change="handleContractTypeChange">
<Option v-for="item in contractTypes" :key="item.id" :value="item.id">{{ item.value || item.name }}</Option>
</Select>
</div>
<div>
<span style="padding: 0 6px;word-break: keep-all;">关键字</span>
@ -70,6 +44,51 @@
/>
</span>
</div>
<div v-if="type!=1">
<span style="padding: 0 6px;word-break: keep-all;">
预算金额
</span>
<InputNumber v-model="select.start_plan_price" :min="0" placeholder="最小金额" style="width: 100px;" />
<span style="padding: 0 5px;">-</span>
<InputNumber v-model="select.end_plan_price" :min="0" placeholder="最大金额" style="width: 100px;" />
</div>
<!-- 更多按钮 -->
<div>
<Button type="text" @click="showMoreSearch = !showMoreSearch">
{{ showMoreSearch ? '收起' : '更多' }}
</Button>
</div>
<!-- 其余搜索项v-if="showMoreSearch" -->
<template v-if="showMoreSearch">
<div>
<span style="padding: 0 6px;word-break: keep-all;">
合同分类
</span>
<Select v-model="select.contract_category" disabled placeholder="请选择合同分类" style="width:140px;" @on-change="handleCategoryChange">
<Option v-for="item in categoryOptions" :key="item.id" :value="item.id">{{ item.value || item.name }}</Option>
</Select>
</div>
<div>
<span style="padding: 0 6px;word-break: keep-all;">
事务类型
</span>
<Select v-model="select.work_type" multiple clearable placeholder="请选择事务类型" style="width:180px;" :max-tag-count="1" @on-change="handleTransactionTypeChange">
<Option v-for="item in transactionTypes" :key="item.id" :value="item.id">{{ item.value || item.name }}</Option>
</Select>
</div>
<div>
<span style="padding: 0 6px;word-break: keep-all;">
合同类型
</span>
<Select v-model="select.contract_type" multiple clearable placeholder="请选择合同类型" style="width:160px;" :max-tag-count="1" @on-change="handleContractTypeChange">
<Option v-for="item in contractTypes" :key="item.id" :value="item.id">{{ item.value || item.name }}</Option>
</Select>
</div>
<div v-if="type!=1">
<span style="padding: 0 6px;word-break: keep-all;">创建日期</span>
<span>
@ -144,14 +163,6 @@
</Select>
</div>
<div v-if="type!=1">
<span style="padding: 0 6px;word-break: keep-all;">
预算金额
</span>
<InputNumber v-model="select.start_plan_price" :min="0" placeholder="最小金额" style="width: 100px;" />
<span style="padding: 0 5px;">-</span>
<InputNumber v-model="select.end_plan_price" :min="0" placeholder="最大金额" style="width: 100px;" />
</div>
<div v-if="type!=1">
<span style="padding: 0 6px;word-break: keep-all;">
@ -219,6 +230,7 @@
</Option>
</Select>
</div>
</template>
<Button style="margin-left: 10px" type="primary" @click="searchContracts"></Button>
<Button
@ -554,6 +566,7 @@ export default {
}
return {
pageTitle: '合同列表',
showMoreSearch:false,
type: 0, // pageType _0 _1
userList: ['liuxiangyu', 'zhushulan', 'admin', 'jiangjiao'],
window: {

@ -0,0 +1,125 @@
<template>
<div class="bar-chart">
<!-- 图表容器 -->
<div ref="chartDom" class="chart-container"></div>
</div>
</template>
<script>
import echarts from 'echarts'; // npm install echarts@4.9.0
export default {
name: 'BarChart',
props: {
// X['A', 'B']
xAxisData: {
type: Array,
required: true,
default: () => []
},
// Y
seriesData: {
type: Array,
required: true,
//
// [
// { name: '', data: [5000, 8000] },
// { name: '', data: [6000, 7500] },
// { name: '使', data: [3000, 5000] }
// ]
default: () => []
}
},
data() {
return {
chartInstance: null //
};
},
watch: {
//
xAxisData: {
deep: true,
handler() {
this.updateChart();
}
},
seriesData: {
deep: true,
handler() {
this.updateChart();
}
}
},
mounted() {
//
this.$nextTick(() => {
this.initChart();
});
},
beforeDestroy() {
//
if (this.chartInstance) {
this.chartInstance.dispose();
}
},
methods: {
//
initChart() {
this.chartInstance = echarts.init(this.$refs.chartDom);
this.updateChart();
},
//
updateChart() {
if (!this.chartInstance) return;
const option = {
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' } //
},
legend: {
// 使 seriesData name
data: this.seriesData.map(item => item.name),
top: 10
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true //
},
xAxis: {
type: 'category',
data: this.xAxisData // Xprop
},
yAxis: {
type: 'value',
name: '金额(元)',
axisLabel: {
formatter: '{value}' // Y
}
},
series: this.seriesData.map(item => ({
...item,
type: 'bar' //
}))
};
this.chartInstance.setOption(option);
}
}
};
</script>
<style scoped>
.bar-chart {
width: 100%;
min-width: 600px;
}
.chart-container {
width: 100%;
height: 400px; /* 固定高度,可根据需求调整 */
}
</style>

@ -1,28 +1,21 @@
<template>
<div>
<el-drawer
size="880px"
title="执行统计"
:visible.sync="drawer"
direction="rtl">
<el-drawer size="880px" title="执行统计" :visible.sync="drawer" direction="rtl">
<div style="padding: 0 20px;">
<template v-if="type === 1">
<Card>
<el-checkbox :indeterminate="isIndeterminate"
v-model="checkAll"
@change="e => {
<el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="e => {
departmentSelect = e ? departments.map(i => (i.plan_department_id)) : [];
isIndeterminate = false;
}">全选</el-checkbox>
<el-checkbox-group v-model="departmentSelect"
size="small"
@change="e => {
<el-checkbox-group style="max-height:200px" v-model="departmentSelect" size="small" @change="e => {
let count = e.length;
checkAll = count === departments.length;
isIndeterminate = count > 0 && count < departments.length;
}">
<el-checkbox v-for="item in departments" :label="item.plan_department_id" :key="item.plan_department_id">{{item.plan_department ? item.plan_department.name : item.plan_department_id}}</el-checkbox>
<el-checkbox v-for="item in departments" :label="item.plan_department_id"
:key="item.plan_department_id">{{item.plan_department ? item.plan_department.name : item.plan_department_id}}</el-checkbox>
</el-checkbox-group>
</Card>
@ -42,22 +35,21 @@
</div>
<div class="item">
<p class="item__title">执行情况</p>
<el-progress class="item__value" text-inside :stroke-width="20" :percentage="totalPercent"></el-progress>
<el-progress class="item__value" text-inside :stroke-width="20"
:percentage="totalPercent"></el-progress>
</div>
</div>
</Card>
</template>
<template v-else>
<Card >
<el-checkbox :indeterminate="isIndeterminate2"
v-model="checkAll2"
@change="e => {
<el-checkbox :indeterminate="isIndeterminate2" v-model="checkAll2" @change="e => {
typeSelect = e ? types.map(i => (i.id)) : [];
isIndeterminate = false;
}">全选</el-checkbox>
<el-checkbox-group v-model="typeSelect"
size="small"
@change="e => {
<el-checkbox-group style="max-height:200px" v-model="typeSelect" size="small" @change="e => {
let count = e.length;
checkAll2 = count === types.length;
isIndeterminate2 = count > 0 && count < types.length;
@ -82,24 +74,41 @@
</div>
<div class="item">
<p class="item__title">执行情况</p>
<el-progress class="item__value" text-inside :stroke-width="20" :percentage="totalPercent"></el-progress>
<el-progress class="item__value" text-inside :stroke-width="20"
:percentage="totalPercent"></el-progress>
</div>
</div>
</Card>
</template>
<!-- <barChart v-if="drawer" :xAxisData="xAxis" :seriesData="seriesData" /> -->
<div class="bar-chart" v-if="drawer">
<!-- 图表容器 -->
<div ref="chartDom" class="chart-container" style="background: #fff; min-height: 400px;"></div>
</div>
</div>
</el-drawer>
</div>
</template>
<script>
import { moneyFormatter } from "@/utils"
import { typeCarry } from "@/api/dashboard/notice"
import * as echarts from 'echarts'
import {
moneyFormatter
} from "@/utils"
import {
typeCarry
} from "@/api/dashboard/notice"
// import barChart from "@/views/dashboard/components/barChart.vue"
export default {
props: {
departments: Array,
year: [Number, String]
},
components: {
// barChart
},
data() {
return {
type: 1, //12
@ -114,7 +123,11 @@ export default {
checkAll2: false,
types: [],
typeSelect: [],
chartInstance: null,
}
},
mounted() {
},
methods: {
moneyFormatter,
@ -126,6 +139,90 @@ export default {
},
setType(type) {
this.type = type
},
//
initChart() {
this.chartInstance = echarts.init(this.$refs.chartDom);
console.log("this.chartInstance", this.chartInstance)
this.updateChart()
},
//
updateChart() {
if (!this.chartInstance) return;
console.log('xAxisData', this.xAxisData);
console.log('ydata1', this.ydata1);
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
}, //
formatter: function(params) {
console.log("params",params)
let result = params[0].axisValue + '<br/>';
params.forEach(item => {
result += item.marker + item.seriesName + ': ' + item.value + '<br/>';
});
return result;
}
},
legend: {
// 使 seriesData name
data: ['年初预算合计金额', '调整后预算合计金额', '已使用'],
top: 10
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true //
},
xAxis: {
type: 'category',
data: this.xAxisData, // computed xAxisData
axisLabel: {
interval: 0,
rotate: 30 //
}
},
yAxis: {
type: 'value',
// name: '',
axisLabel: {
formatter: '{value}' // Y
}
},
series: [{
type:'bar',
name: '年初预算合计金额',
data: this.ydata1, // X
itemStyle: {
color: '#5470C6'
} //
},
{
type:'bar',
name: '调整后预算合计金额',
data: this.ydata2,
itemStyle: {
color: '#91CC75'
}
},
{
type:'bar',
name: '已使用',
data: this.ydata3,
itemStyle: {
color: '#FAC858'
}
}
],
};
this.$nextTick(() => {
this.chartInstance.setOption(option);
})
}
},
computed: {
@ -143,9 +240,13 @@ export default {
},
totalPercent() {
if (this.type === 1) {
return (Number(this.totalMoneyTotal2 !== 0) ? (Math.round(Number(this.totalUseMoneyTotal) / Number(this.totalMoneyTotal2) * 10000)/100) : (Math.round(Number(this.totalUseMoneyTotal) / Number(this.totalMoneyTotal1) * 10000)/100)) || 0
return (Number(this.totalMoneyTotal2 !== 0) ? (Math.round(Number(this.totalUseMoneyTotal) / Number(this
.totalMoneyTotal2) * 10000) / 100) : (Math.round(Number(this.totalUseMoneyTotal) / Number(this
.totalMoneyTotal1) * 10000) / 100)) || 0
} else {
return (Number(this.totalMoneyTotal2Type !== 0) ? (Math.round(Number(this.totalUseMoneyTotalType) / Number(this.totalMoneyTotal2Type) * 10000)/100) : (Math.round(Number(this.totalUseMoneyTotalType) / Number(this.totalMoneyTotal1Type) * 10000)/100)) || 0
return (Number(this.totalMoneyTotal2Type !== 0) ? (Math.round(Number(this.totalUseMoneyTotalType) / Number(
this.totalMoneyTotal2Type) * 10000) / 100) : (Math.round(Number(this.totalUseMoneyTotalType) / Number(
this.totalMoneyTotal1Type) * 10000) / 100)) || 0
}
},
@ -161,6 +262,36 @@ export default {
totalUseMoneyTotalType() {
return this.selectedTypes?.reduce((pre, cur) => (pre + Number(cur.use_money_total || 0)), 0) || 0
},
xAxisData() {
if (this.type == 1) {
return this.selectedDepartments.map(item => item.plan_department?.name || '');
} else {
return this.selectedTypes.map(item => item?.name || '');
}
},
ydata1() {
if (this.type == 1) {
return this.selectedDepartments.map(item => Number(item.money_total_1) || 0)
} else {
return this.selectedTypes.map(item => Number(item.money_total_1) || 0)
}
},
ydata2() {
if (this.type == 1) {
return this.selectedDepartments.map(item => Number(item.money_total_2) || 0)
} else {
return this.selectedTypes.map(item => Number(item.money_total_2) || 0)
}
},
ydata3() {
if (this.type == 1) {
return this.selectedDepartments.map(item => Number(item.use_money_total) || 0)
} else {
return this.selectedTypes.map(item => Number(item.use_money_total) || 0)
}
}
},
watch: {
year: {
@ -169,16 +300,58 @@ export default {
year: val
}).then(res => {
this.types = res
// this.xAxisData = types.map(item=>item.name?item.name:'') // xAxisData computed
console.log(res)
})
},
immediate: true
},
departments:{
handler: function(val) {
// this.xAxisData = val.map(item=>item.plan_department?item.plan_department.name:'') // xAxisData computed
},
immediate: true
},
drawer(newVal) {
if (newVal) {
this.$nextTick(() => {
// this.updateChart();
this.initChart()
})
} else {
if (this.chartInstance) {
this.chartInstance.dispose();
}
}
},
departmentSelect: {
handler() {
if (this.drawer && this.chartInstance) {
this.updateChart();
}
},
deep: true
},
typeSelect: {
handler() {
if (this.drawer && this.chartInstance) {
this.updateChart();
}
},
deep: true
}
}
}
</script>
<style scoped lang="scss">
.chart-container {
width: 80%;
height: 250px;
margin:0 auto;
/* 固定高度,可根据需求调整 */
}
$color: linear-gradient(to top left, #ff6641, #ec3634),
linear-gradient(to top left, #4bfbb2, #49f2ac),
linear-gradient(to top left, #efd458, #ba840a),
@ -218,6 +391,7 @@ linear-gradient(to top left, #a4e829, #06ac2e);
right: 0;
}
}
.item__value {
text-align: center;
flex: 1;
@ -225,15 +399,18 @@ linear-gradient(to top left, #a4e829, #06ac2e);
}
}
}
.content {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-gap: 20px;
padding: 20px 0;
.item__title {
text-align: center;
}
.item__value {
font-weight: 600;
font-size: 17px;
@ -247,6 +424,7 @@ linear-gradient(to top left, #a4e829, #06ac2e);
display: block;
margin-bottom: 6px;
}
::v-deep .el-checkbox-group {
max-height: 300px;
overflow-y: scroll;

@ -60,16 +60,18 @@
<Button type="primary" style="margin-left: 10px" @click="getPlanProgress"></Button>
</slot>
</lx-header>
<xy-table ref="xyTable" :object-span-method="objectSpanMethod" :table-item="table" :list="list" :show-summary="true" :summary-method="summary">
<!-- :object-span-method="objectSpanMethod" -->
<xy-table ref="xyTable"
:defaultExpandAll="false" row-key="id"
:table-item="table" :list="list" :show-summary="true" :summary-method="summary">
<template v-slot:btns>
<div />
</template>
</xy-table>
<div style="display: flex;justify-content: flex-end;">
<Page :total="total" show-elevator @on-change="pageChange" />
</div>
<!-- <div style="display: flex;justify-content: flex-end;">
<Page :total="total" :page-size="select.page_size" show-elevator @on-change="pageChange" />
</div> -->
</div>
</template>
@ -96,6 +98,7 @@ export default {
type: [], //
departments: [],
select: {
page_size:999,
pageIndex: 1,
year: '',
type: '',
@ -126,33 +129,6 @@ export default {
align: 'left',
fixed: 'left'
},
{
prop: 'type',
label: '预算类型',
width: 120,
formatter: (cell, data, value) => {
const res = this.type.filter(item => {
return item.id === value
})
return res[0]?.value || '未知'
}
},
{
prop: 'year',
label: '所属年份',
width: 160
},
{
prop: 'plan_department.name',
label: '相关科室',
width: 180
},
{
prop: 'content',
label: '描述',
align: 'left',
minWidth: 300
},
{
prop: 'money',
width: 180,
@ -199,7 +175,34 @@ export default {
} > </el-progress> </div>
)
}
},
{
prop: 'type',
label: '预算类型',
width: 120,
formatter: (cell, data, value) => {
const res = this.type.filter(item => {
return item.id === value
})
return res[0]?.value || '未知'
}
},
{
prop: 'year',
label: '所属年份',
width: 160
},
{
prop: 'plan_department.name',
label: '相关科室',
width: 180
},
{
prop: 'content',
label: '描述',
align: 'left',
width: 300
},
]
}
},
@ -296,7 +299,7 @@ export default {
async getPlanProgress() {
const res = await getProgress({
page_size: 10,
page_size: this.select.page_size,
page: this.select.pageIndex,
year: this.select.year,
type: this.select.type,
@ -304,23 +307,72 @@ export default {
top_pid: 1,
...this.select
})
for (var m of res.list.data) {
m.pid_info_name = m.pid_info?.name
}
this.list =
mergeTableRow({
data: res.list.data,
mergeColNames: ['pid_info_name'], //
firstMergeColNames: ['pid_info_name'], // firstMerge
firstMerge: 'pid_info_name' //
})
// for (var m of res.list.data) {
// m.pid_info_name = m.pid_info?.name
// }
// this.list =
// mergeTableRow({
// data: res.list.data,
// mergeColNames: ['pid_info_name'], //
// firstMergeColNames: ['pid_info_name'], // firstMerge
// firstMerge: 'pid_info_name' //
// })
this.list = this.concactPid(res.list.data)
this.total = res.list.total
this.useMoneyTotal = res.use_money_total
this.moneyTotal = res.money
this.updateMoneyTotal = res.update_money
this.rateTotal = this.toper(this.updateMoneyTotal, this.moneyTotal, this.useMoneyTotal)
console.log(res)
console.log("list",this.list)
},
concactPid(arr){
const groupByPid = {};
arr.forEach(item => {
const key = item.pid;
if (!groupByPid[key]) {
groupByPid[key] = [];
}
groupByPid[key].push(item);
});
// 2.
const mergedResult = Object.values(groupByPid).map(children => {
// pid_info pid pid_info
const pidInfo = children[0].pid_info;
// use_money_totalchildren use_money_total null 0
const useMoneyTotal = children.reduce((sum, child) => {
const value = child.use_money_total ?? 0; // null
return parseFloat(sum) + parseFloat(value);
}, 0);
//
return {
pid: children[0].pid, // pid pid
id:pidInfo.pid+'-'+pidInfo.id,
pid_info_name: pidInfo.name,
money: parseFloat(pidInfo.money).toFixed(2),
type: pidInfo.type,
update_money: parseFloat(pidInfo.update_money).toFixed(2),
use_money_total: parseFloat(useMoneyTotal).toFixed(2), //
children: children //
};
});
const arrayWithPer = mergedResult.map(row => {
// peruse_money_total / (update_money || money) null NaN
const useMoneyTotal = Number(row.use_money_total ?? 0); // null 0
const denominator = Number(row.update_money) || Number(row.money); // update_money money
const calculation_result = isNaN(useMoneyTotal / denominator) ? 0 : useMoneyTotal / denominator;
return {
...row,
calculation_result: calculation_result // per
};
});
const sortedArray = arrayWithPer.sort((a, b) => b.calculation_result - a.calculation_result);
return sortedArray
}
}
}

Loading…
Cancel
Save