优化提交
This commit is contained in:
parent
7fad93f2ae
commit
9d8a63a6e8
|
@ -2,11 +2,7 @@
|
|||
<el-select
|
||||
v-loading="loading"
|
||||
v-model="selectedValue"
|
||||
filterable
|
||||
remote
|
||||
reserve-keyword
|
||||
placeholder="请输入工序名称/代码"
|
||||
:remote-method="remoteSearch"
|
||||
placeholder="无单价"
|
||||
:loading="loading"
|
||||
@change="handleChange"
|
||||
@focus="handleFocus"
|
||||
|
@ -24,7 +20,6 @@
|
|||
</span>
|
||||
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.code | dv}}</span>
|
||||
</el-option>
|
||||
<el-option v-if="value == null && options.length == 0" disabled label="无单价" :value="null"/>
|
||||
<div style="text-align: center; color: #8492a6; font-size: 13px">
|
||||
共{{ total }}条数据
|
||||
</div>
|
||||
|
@ -116,9 +111,9 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
handleFocus() {
|
||||
if (this.options == null || this.options.length == 0) {
|
||||
this.getOptions();
|
||||
}
|
||||
// if (this.options == null || this.options.length == 0) {
|
||||
// this.getOptions();
|
||||
// }
|
||||
},
|
||||
handleChange(val) {
|
||||
let obj = this.options.find(item => item.priceId == val);
|
||||
|
@ -165,6 +160,9 @@ export default {
|
|||
.empty-select.el-select {
|
||||
.el-input__inner {
|
||||
color: red !important;
|
||||
&::placeholder {
|
||||
color: red !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -77,6 +77,14 @@ export default {
|
|||
headerIcon: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
pageNum: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
pageSize: {
|
||||
type: Number,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -85,7 +93,11 @@ export default {
|
|||
if (isEmpty(this.propPrefix) || isEmpty(this.prop)) {
|
||||
return null;
|
||||
}
|
||||
return `${this.propPrefix}[${index}].${this.prop}`;
|
||||
let rowIndex = index;
|
||||
if (this.pageNum != null && this.pageSize != null) {
|
||||
rowIndex = (this.pageNum - 1) * this.pageSize + index;
|
||||
}
|
||||
return `${this.propPrefix}[${rowIndex}].${this.prop}`;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -7,6 +7,12 @@ const filters = {
|
|||
defaultValue(data) {
|
||||
return data == null || data.length == 0 ? '--' : data;
|
||||
},
|
||||
fix1(num) {
|
||||
if (num == null) {
|
||||
return num;
|
||||
}
|
||||
return num.toFixed(1);
|
||||
},
|
||||
fix2(num) {
|
||||
if (num == null) {
|
||||
return num;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { parseTime } from './ruoyi'
|
||||
import Decimal from "decimal.js";
|
||||
import { parseTime } from './ruoyi';
|
||||
|
||||
/**
|
||||
* 表格时间格式化
|
||||
|
@ -523,3 +523,12 @@ export function formatFraction(numerator, denominator) {
|
|||
}
|
||||
return `${numerator}/${denominator}`;
|
||||
}
|
||||
|
||||
// 保留小数
|
||||
export function toFixed(num, precision = 2) {
|
||||
if (num == null) {
|
||||
return num;
|
||||
}
|
||||
return num.toFixed(precision);
|
||||
}
|
||||
|
||||
|
|
|
@ -229,6 +229,7 @@ export default {
|
|||
{key: 'erpDocumentStatus', visible: false, label: '单据', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
|
||||
{key: 'erpDescription', visible: false, label: '主备注', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'materialNumber', visible: true, label: '物料', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
|
||||
{key: 'fauxPropId', visible: true, label: '辅助属性', minWidth: null, sortable: true, overflow: true, align: 'center', width: null},
|
||||
{key: 'workShopName', visible: true, label: '车间', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
|
||||
{key: 'erpIsRework', visible: true, label: '返工', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"},
|
||||
{key: 'percentage', visible: true, label: '进度', minWidth: null, sortable: false, overflow: false, align: 'left', width: "120"},
|
||||
|
|
|
@ -41,42 +41,42 @@
|
|||
{{d.$index + (pageNum - 1) * pageSize + 1}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<table-form-col label="工序名称" prop-prefix="productList" prop="priceName" :rules="rules.productList.priceName" header-icon="el-icon-edit" @click-header="handleBatchEdit('priceName')">
|
||||
<table-form-col label="工序名称" :page-size="pageSize" :page-num="pageNum" prop-prefix="productList" prop="priceName" :rules="rules.productList.priceName" header-icon="el-icon-edit" @click-header="handleBatchEdit('priceName')">
|
||||
<el-input slot-scope="d" v-model="d.row.priceName" placeholder="请输入工序名称" @change="selectPrice(d.index)" />
|
||||
</table-form-col>
|
||||
<table-form-col label="类别" prop-prefix="productList" prop="priceCategory" width="80" :rules="rules.productList.priceCategory" header-icon="el-icon-edit" @click-header="handleBatchEdit('priceCategory')">
|
||||
<table-form-col label="类别" :page-size="pageSize" :page-num="pageNum" prop-prefix="productList" prop="priceCategory" width="80" :rules="rules.productList.priceCategory" header-icon="el-icon-edit" @click-header="handleBatchEdit('priceCategory')">
|
||||
<el-input slot-scope="d" v-model="d.row.priceCategory" placeholder="请输入类别" @change="selectPrice(d.index)" />
|
||||
</table-form-col>
|
||||
<table-form-col label="大小" prop-prefix="productList" prop="priceSize" width="60" :rules="rules.productList.priceSize" header-icon="el-icon-edit" @click-header="handleBatchEdit('priceSize')">
|
||||
<table-form-col label="大小" :page-size="pageSize" :page-num="pageNum" prop-prefix="productList" prop="priceSize" width="60" :rules="rules.productList.priceSize" header-icon="el-icon-edit" @click-header="handleBatchEdit('priceSize')">
|
||||
<el-input slot-scope="d" v-model="d.row.priceSize" placeholder="请输入大小" @change="selectPrice(d.index)" />
|
||||
</table-form-col>
|
||||
<table-form-col :label="showPattern ? '图案' : ''" prop-prefix="productList" :width="showPattern ? '100' : '0'" prop="pricePattern" :rules="rules.productList.pricePattern" header-icon="el-icon-edit" @click-header="handleBatchEdit('pricePattern')">
|
||||
<table-form-col :label="showPattern ? '图案' : ''" :page-size="pageSize" :page-num="pageNum" prop-prefix="productList" :width="showPattern ? '100' : '0'" prop="pricePattern" :rules="rules.productList.pricePattern" header-icon="el-icon-edit" @click-header="handleBatchEdit('pricePattern')">
|
||||
<el-input slot-scope="d" v-model="d.row.pricePattern" placeholder="请输入图案" @change="selectPrice(d.index)" />
|
||||
</table-form-col>
|
||||
<table-form-col label="成品" prop-prefix="productList" prop="isEnd" :rules="rules.productList.isEnd" required width="60">
|
||||
<table-form-col label="成品" :page-size="pageSize" :page-num="pageNum" prop-prefix="productList" prop="isEnd" :rules="rules.productList.isEnd" required width="60">
|
||||
<el-checkbox slot-scope="d" v-model="d.row.isEnd"/>
|
||||
</table-form-col>
|
||||
<!-- <table-form-col label="不良品" prop-prefix="productList" prop="defectNum">
|
||||
<el-input-number slot-scope="d" v-model="d.row.defectNum" placeholder="请输入数量" :min="0" :precision="0" controls-position="right" style="width: 100%"/>
|
||||
</table-form-col> -->
|
||||
<table-form-col label="表面" width="76" prop-prefix="productList" prop="surface" :rules="rules.productList.surface" header-icon="el-icon-edit" @click-header="handleBatchEdit('surface')">
|
||||
<table-form-col label="表面" :page-size="pageSize" :page-num="pageNum" width="76" prop-prefix="productList" prop="surface" :rules="rules.productList.surface" header-icon="el-icon-edit" @click-header="handleBatchEdit('surface')">
|
||||
<el-select slot-scope="d" v-model="d.row.surface" placeholder="请选择表面处理" @change="onChangeSurface(d.row)" filterable clearable allow-create style="width: 100%;">
|
||||
<el-option v-for="item in dict.type.surface" :key="item.value" :label="item.label" :value="item.value"/>
|
||||
</el-select>
|
||||
</table-form-col>
|
||||
<table-form-col label="颜色" width="115" prop-prefix="productList" prop="color" :rules="rules.productList.color" header-icon="el-icon-edit" @click-header="handleBatchEdit('color')">
|
||||
<table-form-col label="颜色" :page-size="pageSize" :page-num="pageNum" width="115" prop-prefix="productList" prop="color" :rules="rules.productList.color" header-icon="el-icon-edit" @click-header="handleBatchEdit('color')">
|
||||
<el-select slot-scope="d" v-model="d.row.color" placeholder="请选择颜色" filterable clearable allow-create style="width: 100%;">
|
||||
<el-option v-for="item in dict.type.color_code" :key="item.value" :label="item.label" :value="item.value"/>
|
||||
</el-select>
|
||||
</table-form-col>
|
||||
<table-form-col label="良品" prop-prefix="productList" width="100" prop="num" required :rules="rules.productList.num" header-icon="el-icon-edit" @click-header="handleBatchEdit('num')">
|
||||
<table-form-col label="良品" :page-size="pageSize" :page-num="pageNum" prop-prefix="productList" width="100" prop="num" required :rules="rules.productList.num" header-icon="el-icon-edit" @click-header="handleBatchEdit('num')">
|
||||
<el-input slot-scope="d" v-model="d.row.num" placeholder="请输入数量">
|
||||
<template #suffix>
|
||||
{{d.row.priceUnit | dv}}
|
||||
</template>
|
||||
</el-input>
|
||||
</table-form-col>
|
||||
<table-form-col label="单价" prop-prefix="productList" width="100" prop="priceId" required :rules="rules.productList.priceId">
|
||||
<table-form-col label="单价" :page-size="pageSize" :page-num="pageNum" prop-prefix="productList" width="100" prop="priceId" required :rules="rules.productList.priceId">
|
||||
<price-select
|
||||
slot-scope="d"
|
||||
:value="d.row.priceId"
|
||||
|
@ -90,7 +90,7 @@
|
|||
:ref="`priceSelect${d.index}`"
|
||||
/>
|
||||
</table-form-col>
|
||||
<table-form-col label="备注" prop-prefix="productList" prop="remark" align="center" width="60" :rules="rules.productList.remark">
|
||||
<table-form-col label="备注" :page-size="pageSize" :page-num="pageNum" prop-prefix="productList" prop="remark" align="center" width="60" :rules="rules.productList.remark" header-icon="el-icon-edit" @click-header="handleBatchEdit('remark')">
|
||||
<el-popover
|
||||
slot-scope="d"
|
||||
placement="top"
|
||||
|
@ -102,7 +102,7 @@
|
|||
</el-popover>
|
||||
</table-form-col>
|
||||
<table-form-col label="工资" prop-prefix="productList" prop="totalAmount" align="right" width="60">
|
||||
<span slot-scope="d" style="font-size: 12px;" @click="handleDetail(d.row)">{{totalAmount(d.row) | fix2 | dv}}</span>
|
||||
<span slot-scope="d" style="font-size: 12px;" @click="handleDetail(d.row)">{{totalAmount(d.row) | fix1 | dv}}</span>
|
||||
</table-form-col>
|
||||
<table-form-col label="详细" prop-prefix="productList" prop="pricePrice" align="right" width="60" :rules="rules.productList.pricePrice">
|
||||
<div slot-scope="d" @click="handleDetail(d.row)">
|
||||
|
@ -234,6 +234,7 @@ export default {
|
|||
priceSize: '大小',
|
||||
pricePattern: '图案',
|
||||
priceName: '工序',
|
||||
remark: '备注',
|
||||
},
|
||||
autoSumNum: true, // 自动汇总良品
|
||||
showPattern: true, // 显示图案
|
||||
|
@ -262,16 +263,14 @@ export default {
|
|||
eqCategory: row.priceCategory,
|
||||
eqSize: row.priceSize,
|
||||
eqPattern: row.pricePattern,
|
||||
name: row.priceName,
|
||||
eqName: row.priceName,
|
||||
needAllMatch: true
|
||||
}
|
||||
}
|
||||
},
|
||||
totalAmount() {
|
||||
return (row) => {
|
||||
let totalAmount = Decimal(0);
|
||||
row.userProdList.forEach(item => {
|
||||
totalAmount = totalAmount.plus(notNullDecimal(item.num).mul(notNullDecimal(row.pricePrice)));
|
||||
})
|
||||
let totalAmount = notNullDecimal(row.pricePrice).mul(notNullDecimal(row.num));
|
||||
return totalAmount.toNumber();
|
||||
}
|
||||
}
|
||||
|
@ -394,10 +393,10 @@ export default {
|
|||
row.priceQuantityDenominator = val.quantityDenominator || null;
|
||||
row.priceCode = val.code || null;
|
||||
row.priceStatus = val.status || null;
|
||||
row.priceCategory = val.category;
|
||||
row.priceSize = val.size;
|
||||
row.priceName = val.name;
|
||||
row.pricePattern = val.pattern;
|
||||
// row.priceCategory = val.category;
|
||||
// row.priceSize = val.size;
|
||||
// row.priceName = val.name;
|
||||
// row.pricePattern = val.pattern;
|
||||
}
|
||||
},
|
||||
checkPriceChange(ov, nv) {
|
||||
|
@ -512,12 +511,12 @@ export default {
|
|||
inputPlaceholder: `请输入【${fieldName}】`,
|
||||
}).then(({ value }) => {
|
||||
let isEditPrice = ['priceCategory', 'priceSize', 'pricePattern', 'priceName'].includes(prop);
|
||||
for (let i = 0; i < this.rows.length; i++) {
|
||||
let row = this.rows[i];
|
||||
row[prop] = value;
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
if (isEditPrice) {
|
||||
for (let i = 0; i < this.rows.length; i++) {
|
||||
let row = this.rows[i];
|
||||
row[prop] = value;
|
||||
}
|
||||
if (isEditPrice) {
|
||||
for (let i = 0; i < this.rows.length; i++) {
|
||||
let index = this.form.productList.indexOf(this.rows[i]);
|
||||
if (index != -1) {
|
||||
|
@ -614,6 +613,7 @@ export default {
|
|||
defectNum: null,
|
||||
surface: null,
|
||||
color: null,
|
||||
remark: null,
|
||||
sort: this.getNewSort(),
|
||||
// vo
|
||||
priceName: null,
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
</el-input>
|
||||
</table-form-col>
|
||||
<table-form-col label="工资" :prop-prefix="propPrefix" prop="totalAmount" align="right" width="100">
|
||||
<span slot-scope="d" style="font-size: 12px;">{{totalAmount(d.row) | fix2 | dv}}</span>
|
||||
<span slot-scope="d" style="font-size: 12px;">{{totalAmount(d.row) | fix1 | dv}}</span>
|
||||
</table-form-col>
|
||||
<el-table-column label="操作" align="center" width="120">
|
||||
<template #header>
|
||||
|
@ -55,7 +55,7 @@
|
|||
import TableFormCol from '@/components/TableFormCol/index.vue'
|
||||
import UserNewDrawer from '@/components/Business/User/UserNewDrawer.vue'
|
||||
import {listUserWithShift} from "@/api/system/user";
|
||||
import { notNullDecimal } from "@/utils/index";
|
||||
import { notNullDecimal, toFixed } from "@/utils/index";
|
||||
export default {
|
||||
name: "ReportProductUserList",
|
||||
components: {TableFormCol, UserNewDrawer },
|
||||
|
@ -129,7 +129,7 @@ export default {
|
|||
const sum = data.reduce((prev, curr) => {
|
||||
return prev + this.totalAmount(curr);
|
||||
}, 0);
|
||||
sums[index] = sum.toFixed(2);
|
||||
sums[index] = toFixed(sum, 1);
|
||||
} else {
|
||||
sums[index] = '';
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
title="员工产量明细"
|
||||
:visible.sync="visible"
|
||||
width="90%"
|
||||
close-on-click-modal
|
||||
append-to-body
|
||||
>
|
||||
<div class="preview-container" v-if="data != null">
|
||||
|
@ -19,82 +18,115 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 透视表 -->
|
||||
<!-- 搜索和过滤 -->
|
||||
<div class="filter-container">
|
||||
<el-input
|
||||
v-model="searchKey"
|
||||
placeholder="请输入工序名称/员工姓名搜索"
|
||||
clearable
|
||||
size="small"
|
||||
style="width: 300px;"
|
||||
@input="handleSearch"
|
||||
>
|
||||
<el-button slot="append" icon="el-icon-search"></el-button>
|
||||
</el-input>
|
||||
</div>
|
||||
|
||||
<!-- 产量明细表格 -->
|
||||
<el-table
|
||||
v-if="tableData.length"
|
||||
:data="tableData"
|
||||
v-if="filteredData.length"
|
||||
:data="filteredData"
|
||||
style="width: 100%"
|
||||
size="small"
|
||||
size="mini"
|
||||
border
|
||||
:header-cell-style="{ background: '#f5f7fa' }"
|
||||
:cell-style="{ padding: '8px 4px' }"
|
||||
max-height="500px"
|
||||
>
|
||||
<!-- 员工列 -->
|
||||
<el-table-column type="index" label="序号" width="80" align="center" />
|
||||
<!-- 工序名称 -->
|
||||
<el-table-column
|
||||
prop="priceName"
|
||||
label="工序名称"
|
||||
min-width="150"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div class="process-name">
|
||||
<span>{{ scope.row.priceName }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 类别 -->
|
||||
<el-table-column
|
||||
prop="priceCategory"
|
||||
label="类别"
|
||||
min-width="80"
|
||||
align="center"
|
||||
/>
|
||||
|
||||
<!-- 大小 -->
|
||||
<el-table-column
|
||||
prop="priceSize"
|
||||
label="大小"
|
||||
min-width="80"
|
||||
align="center"
|
||||
/>
|
||||
|
||||
<!-- 图案 -->
|
||||
<el-table-column
|
||||
prop="pricePattern"
|
||||
label="图案"
|
||||
min-width="100"
|
||||
align="center"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!-- 单价 -->
|
||||
<el-table-column
|
||||
prop="pricePrice"
|
||||
label="单价"
|
||||
min-width="100"
|
||||
align="center"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
|
||||
<!-- 员工 -->
|
||||
<el-table-column
|
||||
prop="userName"
|
||||
label="员工"
|
||||
fixed="left"
|
||||
min-width="120"
|
||||
align="center"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div class="user-info">
|
||||
<span class="user-name">{{ scope.row.userName }}</span>
|
||||
<span class="user-no" v-if="scope.row.userNo">({{ scope.row.userNo }})</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 产量 -->
|
||||
<el-table-column
|
||||
prop="num"
|
||||
label="产量"
|
||||
min-width="100"
|
||||
align="center"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span class="user-name">{{ scope.row.userName }}</span>
|
||||
<span class="prod-num">{{ scope.row.num }}</span>
|
||||
<span class="prod-unit">{{ scope.row.priceUnit }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 动态生成工序列 -->
|
||||
<el-table-column
|
||||
v-for="process in processList"
|
||||
:key="process.priceId"
|
||||
:label="process.priceName"
|
||||
align="center"
|
||||
min-width="200"
|
||||
>
|
||||
<template slot="header" slot-scope="scope">
|
||||
<div class="process-header">
|
||||
<div class="process-title">
|
||||
<div class="process-name" :title="process.priceName">{{ process.priceName }}</div>
|
||||
<div class="process-code" :title="process.priceCode">{{ process.priceCode }}</div>
|
||||
</div>
|
||||
<div class="process-info">
|
||||
<span class="info-item">
|
||||
<i class="el-icon-box"></i>
|
||||
<span>{{ process.num }}{{ process.priceUnit }}</span>
|
||||
</span>
|
||||
<span class="info-item">
|
||||
<i class="el-icon-money"></i>
|
||||
<span>{{ process.pricePrice }}元/{{ process.priceUnit }}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<template v-if="scope.row.products[process.priceId]">
|
||||
<div class="prod-cell">
|
||||
<div class="prod-num">
|
||||
<span class="num">{{ scope.row.products[process.priceId].num }}</span>
|
||||
<span class="unit">{{ process.priceUnit }}</span>
|
||||
</div>
|
||||
<div class="prod-amount">
|
||||
<span class="amount">{{ calculateIncome(scope.row.products[process.priceId].num, process.pricePrice) }}</span>
|
||||
<span class="unit">元</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 合计列 -->
|
||||
<!-- 工资 -->
|
||||
<el-table-column
|
||||
label="合计金额"
|
||||
fixed="right"
|
||||
min-width="120"
|
||||
align="center"
|
||||
class-name="total-column"
|
||||
label="工资"
|
||||
min-width="100"
|
||||
align="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span class="total-income">{{ scope.row.totalAmount }}元</span>
|
||||
<span class="prod-amount">{{ calculateIncome(scope.row.num, scope.row.pricePrice) }} 元</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
@ -128,71 +160,76 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false
|
||||
visible: false,
|
||||
searchKey: '',
|
||||
filteredData: [],
|
||||
spanArr: [] // 存储合并信息
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 获取所有工序列表
|
||||
processList() {
|
||||
return (this.data?.productList || []).filter(item =>
|
||||
item && item.userProdList && item.userProdList.length > 0
|
||||
);
|
||||
},
|
||||
// 计算表格数据
|
||||
tableData() {
|
||||
// 获取所有用户产量数据
|
||||
allUserProdData() {
|
||||
if (!this.data || !this.data.productList) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const userMap = new Map();
|
||||
const result = [];
|
||||
|
||||
// 遍历所有工序
|
||||
this.processList.forEach(process => {
|
||||
if (!process.userProdList) return;
|
||||
(this.data.productList || []).forEach(product => {
|
||||
if (!product.userProdList || product.userProdList.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 遍历工序下的所有用户产量
|
||||
process.userProdList.forEach(userProd => {
|
||||
product.userProdList.forEach(userProd => {
|
||||
if (!userProd || !userProd.userId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!userMap.has(userProd.userId)) {
|
||||
userMap.set(userProd.userId, {
|
||||
userId: userProd.userId,
|
||||
userName: userProd.userName || '',
|
||||
products: {},
|
||||
totalAmount: 0
|
||||
});
|
||||
}
|
||||
|
||||
const userData = userMap.get(userProd.userId);
|
||||
userData.products[process.priceId] = {
|
||||
num: userProd.num || 0,
|
||||
amount: this.calculateIncome(userProd.num, process.pricePrice)
|
||||
};
|
||||
userData.totalAmount = new Decimal(userData.totalAmount)
|
||||
.plus(userData.products[process.priceId].amount)
|
||||
.toNumber();
|
||||
result.push({
|
||||
// 工序信息
|
||||
priceId: product.priceId,
|
||||
priceName: product.priceName,
|
||||
priceCode: product.priceCode,
|
||||
priceCategory: product.priceCategory,
|
||||
priceSize: product.priceSize,
|
||||
pricePattern: product.pricePattern,
|
||||
priceUnit: product.priceUnit,
|
||||
pricePrice: product.pricePrice,
|
||||
|
||||
// 用户信息
|
||||
userId: userProd.userId,
|
||||
userName: userProd.userName,
|
||||
userNo: userProd.userNo,
|
||||
|
||||
// 产量信息
|
||||
num: userProd.num,
|
||||
amount: this.calculateIncome(userProd.num, product.pricePrice)
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return Array.from(userMap.values());
|
||||
return result;
|
||||
},
|
||||
// 计算总金额
|
||||
totalAmount() {
|
||||
if (!this.tableData.length) {
|
||||
return '0.00';
|
||||
if (!this.allUserProdData.length) {
|
||||
return '0.0';
|
||||
}
|
||||
|
||||
return this.tableData.reduce((sum, row) => {
|
||||
return new Decimal(sum).plus(row.totalAmount || 0).toNumber();
|
||||
}, 0).toFixed(2);
|
||||
return this.allUserProdData.reduce((sum, item) => {
|
||||
return new Decimal(sum).plus(this.calculateIncome(item.num, item.pricePrice) || 0).toNumber();
|
||||
}, 0).toFixed(1);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show: {
|
||||
handler(val) {
|
||||
this.visible = val;
|
||||
if (val) {
|
||||
this.handleSearch();
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
|
@ -200,15 +237,156 @@ export default {
|
|||
if (!val) {
|
||||
this.$emit('update:show', false);
|
||||
}
|
||||
},
|
||||
allUserProdData: {
|
||||
handler() {
|
||||
this.handleSearch();
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 计算工资
|
||||
calculateIncome(num, price) {
|
||||
if (!num || !price) {
|
||||
return '0.00';
|
||||
return '0.0';
|
||||
}
|
||||
return calcMulDecimal(num, price).toFixed(2);
|
||||
return calcMulDecimal(num, price).toFixed(1);
|
||||
},
|
||||
// 搜索过滤
|
||||
handleSearch() {
|
||||
const key = this.searchKey.toLowerCase().trim();
|
||||
if (!key) {
|
||||
this.filteredData = [...this.allUserProdData];
|
||||
} else {
|
||||
this.filteredData = this.allUserProdData.filter(item => {
|
||||
return (
|
||||
(item.priceName && item.priceName.toLowerCase().includes(key)) ||
|
||||
(item.userName && item.userName.toLowerCase().includes(key)) ||
|
||||
(item.priceCode && item.priceCode.toLowerCase().includes(key))
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// 对数据进行排序
|
||||
this.sortDataForMerge();
|
||||
|
||||
// 计算合并信息
|
||||
this.getSpanArr();
|
||||
},
|
||||
// 对数据进行排序,便于合并
|
||||
sortDataForMerge() {
|
||||
this.filteredData.sort((a, b) => {
|
||||
// 按工序名称、类别、大小、图案排序
|
||||
if (a.priceName !== b.priceName) {
|
||||
return a.priceName.localeCompare(b.priceName);
|
||||
}
|
||||
if (a.priceCategory !== b.priceCategory) {
|
||||
return (a.priceCategory || '').localeCompare(b.priceCategory || '');
|
||||
}
|
||||
if (a.priceSize !== b.priceSize) {
|
||||
return (a.priceSize || '').localeCompare(b.priceSize || '');
|
||||
}
|
||||
if (a.pricePattern !== b.pricePattern) {
|
||||
return (a.pricePattern || '').localeCompare(b.pricePattern || '');
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
},
|
||||
// 计算合并信息
|
||||
getSpanArr() {
|
||||
this.spanArr = [];
|
||||
if (!this.filteredData.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 初始化合并数组,每个单元格默认占一行一列
|
||||
for (let i = 0; i < this.filteredData.length; i++) {
|
||||
if (!this.spanArr[i]) {
|
||||
this.spanArr[i] = {
|
||||
priceName: 1, // 工序名称列占的行数
|
||||
priceCategory: 1, // 类别列占的行数
|
||||
priceSize: 1, // 大小列占的行数
|
||||
pricePattern: 1, // 图案列占的行数
|
||||
pricePrice: 1 // 单价列占的行数
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 计算每个单元格合并的行数
|
||||
for (let i = 0; i < this.filteredData.length; i++) {
|
||||
if (i === 0) continue; // 跳过第一行
|
||||
|
||||
const current = this.filteredData[i];
|
||||
const prev = this.filteredData[i - 1];
|
||||
|
||||
// 如果当前行与上一行的工序名称相同
|
||||
if (current.priceName === prev.priceName) {
|
||||
this.spanArr[i].priceName = 0; // 当前行的工序名称不显示
|
||||
this.spanArr[i - this.getPrevRowIndex(i, 'priceName')].priceName++; // 上一个显示工序名称的行合并行数+1
|
||||
|
||||
// 如果当前行与上一行的类别相同
|
||||
if (current.priceCategory === prev.priceCategory) {
|
||||
this.spanArr[i].priceCategory = 0; // 当前行的类别不显示
|
||||
this.spanArr[i - this.getPrevRowIndex(i, 'priceCategory')].priceCategory++; // 上一个显示类别的行合并行数+1
|
||||
|
||||
// 如果当前行与上一行的大小相同
|
||||
if (current.priceSize === prev.priceSize) {
|
||||
this.spanArr[i].priceSize = 0; // 当前行的大小不显示
|
||||
this.spanArr[i - this.getPrevRowIndex(i, 'priceSize')].priceSize++; // 上一个显示大小的行合并行数+1
|
||||
|
||||
// 如果当前行与上一行的图案相同
|
||||
if (current.pricePattern === prev.pricePattern) {
|
||||
this.spanArr[i].pricePattern = 0; // 当前行的图案不显示
|
||||
this.spanArr[i - this.getPrevRowIndex(i, 'pricePattern')].pricePattern++; // 上一个显示图案的行合并行数+1
|
||||
|
||||
// 如果当前行与上一行的单价相同
|
||||
if (current.pricePrice === prev.pricePrice) {
|
||||
this.spanArr[i].pricePrice = 0; // 当前行的单价不显示
|
||||
this.spanArr[i - this.getPrevRowIndex(i, 'pricePrice')].pricePrice++; // 上一个显示单价的行合并行数+1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 获取上一个显示该列的行索引
|
||||
getPrevRowIndex(currentIndex, prop) {
|
||||
let prevIndex = 1;
|
||||
for (let i = currentIndex - 1; i >= 0; i--) {
|
||||
if (this.spanArr[i][prop] !== 0) {
|
||||
break;
|
||||
}
|
||||
prevIndex++;
|
||||
}
|
||||
return prevIndex;
|
||||
},
|
||||
// 合并行方法
|
||||
arraySpanMethod({ row, column, rowIndex, columnIndex }) {
|
||||
if (!this.spanArr.length) {
|
||||
return [1, 1];
|
||||
}
|
||||
|
||||
// 根据列索引返回对应的合并信息
|
||||
if (columnIndex === 0) { // 工序名称
|
||||
const rowspan = this.spanArr[rowIndex].priceName;
|
||||
return rowspan ? [rowspan, 1] : [0, 0];
|
||||
} else if (columnIndex === 1) { // 类别
|
||||
const rowspan = this.spanArr[rowIndex].priceCategory;
|
||||
return rowspan ? [rowspan, 1] : [0, 0];
|
||||
} else if (columnIndex === 2) { // 大小
|
||||
const rowspan = this.spanArr[rowIndex].priceSize;
|
||||
return rowspan ? [rowspan, 1] : [0, 0];
|
||||
} else if (columnIndex === 3) { // 图案
|
||||
const rowspan = this.spanArr[rowIndex].pricePattern;
|
||||
return rowspan ? [rowspan, 1] : [0, 0];
|
||||
} else if (columnIndex === 4) { // 单价
|
||||
const rowspan = this.spanArr[rowIndex].pricePrice;
|
||||
return rowspan ? [rowspan, 1] : [0, 0];
|
||||
}
|
||||
|
||||
return [1, 1]; // 其他列不合并
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -241,84 +419,48 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
:deep(.el-table) {
|
||||
.process-header {
|
||||
padding: 4px;
|
||||
|
||||
.process-title {
|
||||
margin-bottom: 4px;
|
||||
|
||||
.process-name {
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.process-code {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-top: 2px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.process-info {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-top: 4px;
|
||||
padding-top: 4px;
|
||||
border-top: 1px dashed #ebeef5;
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
i {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.filter-container {
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.prod-cell {
|
||||
:deep(.el-table) {
|
||||
.process-name {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
|
||||
.prod-num {
|
||||
color: #303133;
|
||||
font-weight: 500;
|
||||
|
||||
.unit {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-left: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.prod-amount {
|
||||
.process-code {
|
||||
font-size: 12px;
|
||||
color: #67c23a;
|
||||
|
||||
.unit {
|
||||
margin-left: 2px;
|
||||
}
|
||||
color: #909399;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.total-column {
|
||||
background-color: #fafafa;
|
||||
.user-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.user-no {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.total-income {
|
||||
color: #409EFF;
|
||||
.prod-num {
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.prod-unit {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.prod-amount {
|
||||
color: #67c23a;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
@ -327,21 +469,9 @@ export default {
|
|||
// 添加响应式布局支持
|
||||
@media screen and (max-width: 1024px) {
|
||||
.preview-container {
|
||||
:deep(.el-table) {
|
||||
.process-header {
|
||||
.process-title {
|
||||
.process-name, .process-code {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.process-info {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding-top: 6px;
|
||||
}
|
||||
}
|
||||
.summary-info {
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
<dict-tag :options="dict.type.report_status" :value="d.row[column.key]" size="mini"/>
|
||||
</template>
|
||||
<template v-else-if="column.key === 'totalAmount'">
|
||||
{{d.row.totalAmount | dv}} 元
|
||||
{{d.row.totalAmount | fix1 | dv}} 元
|
||||
</template>
|
||||
<template v-else-if="column.key === 'createTime'">
|
||||
<template v-if="d.row.createTime">创建:{{d.row.createTime | dv}}({{d.row.createBy | dv}})<br/></template>
|
||||
|
@ -170,7 +170,7 @@ import {$showColumns} from '@/utils/mixins';
|
|||
import FormCol from "@/components/FormCol/index.vue";
|
||||
import {DatePickerOptions, ReportStatus} from "@/utils/constants";
|
||||
import DeptSelect from '@/components/Business/Dept/DeptSelect.vue';
|
||||
|
||||
import {toFixed} from '@/utils/index';
|
||||
// 默认排序字段
|
||||
const defaultSort = {
|
||||
prop: "createTime",
|
||||
|
@ -192,8 +192,8 @@ export default {
|
|||
{key: 'deptName', visible: true, label: '部门', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'reportDate', visible: true, label: '日期', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'status', visible: true, label: '状态', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'totalAmount', visible: true, label: '金额', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'productCount', visible: true, label: '工序', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'productCount', visible: true, label: '工序', minWidth: null, sortable: false, overflow: false, align: 'center', width: null},
|
||||
{key: 'totalAmount', visible: true, label: '金额', minWidth: null, sortable: true, overflow: false, align: 'right', width: null},
|
||||
{key: 'createTime', visible: true, label: '时间', minWidth: null, sortable: true, overflow: false, align: 'left', width: "250"},
|
||||
{key: 'verifyRemark', visible: true, label: '审核意见', minWidth: null, sortable: false, overflow: true, align: 'center', width: null},
|
||||
],
|
||||
|
@ -274,7 +274,7 @@ export default {
|
|||
return;
|
||||
}
|
||||
if (column.property === 'totalAmount') {
|
||||
sums[index] = this.sum.totalAmount + ' 元';
|
||||
sums[index] = toFixed(this.sum.totalAmount, 1) + ' 元';
|
||||
} else {
|
||||
sums[index] = '';
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@
|
|||
{{d.row[column.key] | dv}} {{d.row.priceUnit | dv}}
|
||||
</template>
|
||||
<template v-else-if="['totalAmount'].includes(column.key)">
|
||||
{{d.row[column.key] | dv}} 元
|
||||
{{d.row[column.key] | fix1 | dv}} 元
|
||||
</template>
|
||||
<template v-else-if="['pricePrice'].includes(column.key)">
|
||||
<template v-if="d.row.priceId">
|
||||
|
@ -197,7 +197,7 @@ import SearchFormItem from "@/components/SearchFormItem/index.vue";
|
|||
import ReportUserProd from "@/views/yh/reportUserProd/index.vue";
|
||||
import {calcMulDecimal} from "@/utils/money";
|
||||
import ReportUserProdDescriptions from "@/views/yh/reportProd/components/ReportUserProdDescriptions.vue";
|
||||
import {formatFraction, isEmpty} from "@/utils";
|
||||
import {formatFraction, isEmpty, toFixed} from "@/utils";
|
||||
import ReportOrderProdDescriptions from "@/views/yh/reportProd/components/ReportOrderProdDescriptions.vue";
|
||||
import BooleanTag from '@/components/BooleanTag/index.vue'
|
||||
import {ReportStatus} from "@/utils/constants";
|
||||
|
@ -262,8 +262,8 @@ export default {
|
|||
{key: 'color', visible: false, label: '颜色', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'num', visible: true, label: '良品', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'defectNum', visible: false, label: '不良品', minWidth: null, sortable: true, overflow: false, align: 'center', width: "100"},
|
||||
{key: 'pricePrice', visible: true, label: '单价', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'totalAmount', visible: true, label: '总价', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'pricePrice', visible: true, label: '单价', minWidth: null, sortable: true, overflow: false, align: 'right', width: null},
|
||||
{key: 'totalAmount', visible: true, label: '总价', minWidth: null, sortable: true, overflow: false, align: 'right', width: null},
|
||||
{key: 'priceSpec', visible: false, label: '规格', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'priceClassify', visible: false, label: '分类', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
{key: 'priceQuantity', visible: false, label: '倍数', minWidth: null, sortable: true, overflow: false, align: 'center', width: null},
|
||||
|
@ -367,7 +367,7 @@ export default {
|
|||
if (column.property === 'num') {
|
||||
sums[index] = this.sum.num;
|
||||
} else if (column.property === 'totalAmount') {
|
||||
sums[index] = this.sum.totalAmount + ' 元';
|
||||
sums[index] = toFixed(this.sum.totalAmount, 1) + ' 元';
|
||||
} else {
|
||||
sums[index] = '';
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@
|
|||
{{d.row[column.key] | dv}} {{ d.row.priceUnit | dv}}
|
||||
</template>
|
||||
<template v-else-if="column.key === 'totalPrice'">
|
||||
{{d.row.totalPrice | fix2 | dv}} 元
|
||||
{{d.row.totalPrice | fix1 | dv}} 元
|
||||
</template>
|
||||
<template v-else-if="column.key === 'reportStatus'">
|
||||
<dict-tag :value="d.row.reportStatus" :options="dict.type.report_status" size="mini"/>
|
||||
|
@ -243,6 +243,7 @@ import FormCol from "@/components/FormCol/index.vue";
|
|||
import DeptSelect from '@/components/Business/Dept/DeptSelect.vue';
|
||||
import {dashboardUserProd} from '@/api/yh/dashboard.js';
|
||||
import {getReportUserProdSum} from '@/api/dashboard/reportUserProd';
|
||||
import {toFixed} from '@/utils/index';
|
||||
|
||||
// 默认排序字段
|
||||
const defaultSort = {
|
||||
|
@ -358,7 +359,7 @@ export default {
|
|||
return;
|
||||
}
|
||||
if (column.property === 'totalPrice') {
|
||||
sums[index] = this.sum.totalAmount + ' 元';
|
||||
sums[index] = toFixed(this.sum.totalAmount, 1) + ' 元';
|
||||
} else if (column.property === 'num') {
|
||||
sums[index] = this.sum.num;
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue
Block a user