优化提交

This commit is contained in:
磷叶 2025-03-05 18:03:44 +08:00
parent 7fad93f2ae
commit 9d8a63a6e8
11 changed files with 387 additions and 230 deletions

View File

@ -2,11 +2,7 @@
<el-select <el-select
v-loading="loading" v-loading="loading"
v-model="selectedValue" v-model="selectedValue"
filterable placeholder="无单价"
remote
reserve-keyword
placeholder="请输入工序名称/代码"
:remote-method="remoteSearch"
:loading="loading" :loading="loading"
@change="handleChange" @change="handleChange"
@focus="handleFocus" @focus="handleFocus"
@ -24,7 +20,6 @@
</span> </span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.code | dv}}</span> <span style="float: right; color: #8492a6; font-size: 13px">{{ item.code | dv}}</span>
</el-option> </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"> <div style="text-align: center; color: #8492a6; font-size: 13px">
{{ total }}条数据 {{ total }}条数据
</div> </div>
@ -116,9 +111,9 @@ export default {
}, },
methods: { methods: {
handleFocus() { handleFocus() {
if (this.options == null || this.options.length == 0) { // if (this.options == null || this.options.length == 0) {
this.getOptions(); // this.getOptions();
} // }
}, },
handleChange(val) { handleChange(val) {
let obj = this.options.find(item => item.priceId == val); let obj = this.options.find(item => item.priceId == val);
@ -165,6 +160,9 @@ export default {
.empty-select.el-select { .empty-select.el-select {
.el-input__inner { .el-input__inner {
color: red !important; color: red !important;
&::placeholder {
color: red !important;
}
} }
} }
</style> </style>

View File

@ -77,6 +77,14 @@ export default {
headerIcon: { headerIcon: {
type: String, type: String,
default: null, default: null,
},
pageNum: {
type: Number,
default: null
},
pageSize: {
type: Number,
default: null
} }
}, },
computed: { computed: {
@ -85,7 +93,11 @@ export default {
if (isEmpty(this.propPrefix) || isEmpty(this.prop)) { if (isEmpty(this.propPrefix) || isEmpty(this.prop)) {
return null; 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}`;
} }
} }
}, },

View File

@ -7,6 +7,12 @@ const filters = {
defaultValue(data) { defaultValue(data) {
return data == null || data.length == 0 ? '--' : data; return data == null || data.length == 0 ? '--' : data;
}, },
fix1(num) {
if (num == null) {
return num;
}
return num.toFixed(1);
},
fix2(num) { fix2(num) {
if (num == null) { if (num == null) {
return num; return num;

View File

@ -1,5 +1,5 @@
import { parseTime } from './ruoyi'
import Decimal from "decimal.js"; import Decimal from "decimal.js";
import { parseTime } from './ruoyi';
/** /**
* 表格时间格式化 * 表格时间格式化
@ -523,3 +523,12 @@ export function formatFraction(numerator, denominator) {
} }
return `${numerator}/${denominator}`; return `${numerator}/${denominator}`;
} }
// 保留小数
export function toFixed(num, precision = 2) {
if (num == null) {
return num;
}
return num.toFixed(precision);
}

View File

@ -229,6 +229,7 @@ export default {
{key: 'erpDocumentStatus', visible: false, label: '单据', minWidth: null, sortable: true, overflow: false, align: 'center', width: "80"}, {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: '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: '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: '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: '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"}, {key: 'percentage', visible: true, label: '进度', minWidth: null, sortable: false, overflow: false, align: 'left', width: "120"},

View File

@ -41,42 +41,42 @@
{{d.$index + (pageNum - 1) * pageSize + 1}} {{d.$index + (pageNum - 1) * pageSize + 1}}
</template> </template>
</el-table-column> </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)" /> <el-input slot-scope="d" v-model="d.row.priceName" placeholder="请输入工序名称" @change="selectPrice(d.index)" />
</table-form-col> </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)" /> <el-input slot-scope="d" v-model="d.row.priceCategory" placeholder="请输入类别" @change="selectPrice(d.index)" />
</table-form-col> </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)" /> <el-input slot-scope="d" v-model="d.row.priceSize" placeholder="请输入大小" @change="selectPrice(d.index)" />
</table-form-col> </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)" /> <el-input slot-scope="d" v-model="d.row.pricePattern" placeholder="请输入图案" @change="selectPrice(d.index)" />
</table-form-col> </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"/> <el-checkbox slot-scope="d" v-model="d.row.isEnd"/>
</table-form-col> </table-form-col>
<!-- <table-form-col label="不良品" prop-prefix="productList" prop="defectNum"> <!-- <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%"/> <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> -->
<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-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-option v-for="item in dict.type.surface" :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>
</table-form-col> </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-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-option v-for="item in dict.type.color_code" :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>
</table-form-col> </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="请输入数量"> <el-input slot-scope="d" v-model="d.row.num" placeholder="请输入数量">
<template #suffix> <template #suffix>
{{d.row.priceUnit | dv}} {{d.row.priceUnit | dv}}
</template> </template>
</el-input> </el-input>
</table-form-col> </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 <price-select
slot-scope="d" slot-scope="d"
:value="d.row.priceId" :value="d.row.priceId"
@ -90,7 +90,7 @@
:ref="`priceSelect${d.index}`" :ref="`priceSelect${d.index}`"
/> />
</table-form-col> </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 <el-popover
slot-scope="d" slot-scope="d"
placement="top" placement="top"
@ -102,7 +102,7 @@
</el-popover> </el-popover>
</table-form-col> </table-form-col>
<table-form-col label="工资" prop-prefix="productList" prop="totalAmount" align="right" width="60"> <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>
<table-form-col label="详细" prop-prefix="productList" prop="pricePrice" align="right" width="60" :rules="rules.productList.pricePrice"> <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)"> <div slot-scope="d" @click="handleDetail(d.row)">
@ -234,6 +234,7 @@ export default {
priceSize: '大小', priceSize: '大小',
pricePattern: '图案', pricePattern: '图案',
priceName: '工序', priceName: '工序',
remark: '备注',
}, },
autoSumNum: true, // autoSumNum: true, //
showPattern: true, // showPattern: true, //
@ -262,16 +263,14 @@ export default {
eqCategory: row.priceCategory, eqCategory: row.priceCategory,
eqSize: row.priceSize, eqSize: row.priceSize,
eqPattern: row.pricePattern, eqPattern: row.pricePattern,
name: row.priceName, eqName: row.priceName,
needAllMatch: true
} }
} }
}, },
totalAmount() { totalAmount() {
return (row) => { return (row) => {
let totalAmount = Decimal(0); let totalAmount = notNullDecimal(row.pricePrice).mul(notNullDecimal(row.num));
row.userProdList.forEach(item => {
totalAmount = totalAmount.plus(notNullDecimal(item.num).mul(notNullDecimal(row.pricePrice)));
})
return totalAmount.toNumber(); return totalAmount.toNumber();
} }
} }
@ -394,10 +393,10 @@ export default {
row.priceQuantityDenominator = val.quantityDenominator || null; row.priceQuantityDenominator = val.quantityDenominator || null;
row.priceCode = val.code || null; row.priceCode = val.code || null;
row.priceStatus = val.status || null; row.priceStatus = val.status || null;
row.priceCategory = val.category; // row.priceCategory = val.category;
row.priceSize = val.size; // row.priceSize = val.size;
row.priceName = val.name; // row.priceName = val.name;
row.pricePattern = val.pattern; // row.pricePattern = val.pattern;
} }
}, },
checkPriceChange(ov, nv) { checkPriceChange(ov, nv) {
@ -512,11 +511,11 @@ export default {
inputPlaceholder: `请输入【${fieldName}`, inputPlaceholder: `请输入【${fieldName}`,
}).then(({ value }) => { }).then(({ value }) => {
let isEditPrice = ['priceCategory', 'priceSize', 'pricePattern', 'priceName'].includes(prop); 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(() => { this.$nextTick(() => {
for (let i = 0; i < this.rows.length; i++) {
let row = this.rows[i];
row[prop] = value;
}
if (isEditPrice) { if (isEditPrice) {
for (let i = 0; i < this.rows.length; i++) { for (let i = 0; i < this.rows.length; i++) {
let index = this.form.productList.indexOf(this.rows[i]); let index = this.form.productList.indexOf(this.rows[i]);
@ -614,6 +613,7 @@ export default {
defectNum: null, defectNum: null,
surface: null, surface: null,
color: null, color: null,
remark: null,
sort: this.getNewSort(), sort: this.getNewSort(),
// vo // vo
priceName: null, priceName: null,

View File

@ -24,7 +24,7 @@
</el-input> </el-input>
</table-form-col> </table-form-col>
<table-form-col label="工资" :prop-prefix="propPrefix" prop="totalAmount" align="right" width="100"> <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> </table-form-col>
<el-table-column label="操作" align="center" width="120"> <el-table-column label="操作" align="center" width="120">
<template #header> <template #header>
@ -55,7 +55,7 @@
import TableFormCol from '@/components/TableFormCol/index.vue' import TableFormCol from '@/components/TableFormCol/index.vue'
import UserNewDrawer from '@/components/Business/User/UserNewDrawer.vue' import UserNewDrawer from '@/components/Business/User/UserNewDrawer.vue'
import {listUserWithShift} from "@/api/system/user"; import {listUserWithShift} from "@/api/system/user";
import { notNullDecimal } from "@/utils/index"; import { notNullDecimal, toFixed } from "@/utils/index";
export default { export default {
name: "ReportProductUserList", name: "ReportProductUserList",
components: {TableFormCol, UserNewDrawer }, components: {TableFormCol, UserNewDrawer },
@ -129,7 +129,7 @@ export default {
const sum = data.reduce((prev, curr) => { const sum = data.reduce((prev, curr) => {
return prev + this.totalAmount(curr); return prev + this.totalAmount(curr);
}, 0); }, 0);
sums[index] = sum.toFixed(2); sums[index] = toFixed(sum, 1);
} else { } else {
sums[index] = ''; sums[index] = '';
} }

View File

@ -3,7 +3,6 @@
title="员工产量明细" title="员工产量明细"
:visible.sync="visible" :visible.sync="visible"
width="90%" width="90%"
close-on-click-modal
append-to-body append-to-body
> >
<div class="preview-container" v-if="data != null"> <div class="preview-container" v-if="data != null">
@ -19,82 +18,115 @@
</div> </div>
</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 <el-table
v-if="tableData.length" v-if="filteredData.length"
:data="tableData" :data="filteredData"
style="width: 100%" style="width: 100%"
size="small" size="mini"
border border
:header-cell-style="{ background: '#f5f7fa' }" :header-cell-style="{ background: '#f5f7fa' }"
:cell-style="{ padding: '8px 4px' }" :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 <el-table-column
prop="userName" prop="userName"
label="员工" 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" min-width="100"
align="center" align="center"
> >
<template slot-scope="scope"> <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> </template>
</el-table-column> </el-table-column>
<!-- 动态生成工序列 --> <!-- 工资 -->
<el-table-column <el-table-column
v-for="process in processList" label="工资"
:key="process.priceId" min-width="100"
:label="process.priceName" align="right"
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"
> >
<template slot-scope="scope"> <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> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -128,71 +160,76 @@ export default {
}, },
data() { data() {
return { return {
visible: false visible: false,
searchKey: '',
filteredData: [],
spanArr: [] //
} }
}, },
computed: { computed: {
// //
processList() { allUserProdData() {
return (this.data?.productList || []).filter(item =>
item && item.userProdList && item.userProdList.length > 0
);
},
//
tableData() {
if (!this.data || !this.data.productList) { if (!this.data || !this.data.productList) {
return []; return [];
} }
const userMap = new Map(); const result = [];
// //
this.processList.forEach(process => { (this.data.productList || []).forEach(product => {
if (!process.userProdList) return; if (!product.userProdList || product.userProdList.length === 0) {
return;
}
// //
process.userProdList.forEach(userProd => { product.userProdList.forEach(userProd => {
if (!userProd || !userProd.userId) { if (!userProd || !userProd.userId) {
return; return;
} }
if (!userMap.has(userProd.userId)) { result.push({
userMap.set(userProd.userId, { //
userId: userProd.userId, priceId: product.priceId,
userName: userProd.userName || '', priceName: product.priceName,
products: {}, priceCode: product.priceCode,
totalAmount: 0 priceCategory: product.priceCategory,
}); priceSize: product.priceSize,
} pricePattern: product.pricePattern,
priceUnit: product.priceUnit,
pricePrice: product.pricePrice,
const userData = userMap.get(userProd.userId); //
userData.products[process.priceId] = { userId: userProd.userId,
num: userProd.num || 0, userName: userProd.userName,
amount: this.calculateIncome(userProd.num, process.pricePrice) userNo: userProd.userNo,
};
userData.totalAmount = new Decimal(userData.totalAmount) //
.plus(userData.products[process.priceId].amount) num: userProd.num,
.toNumber(); amount: this.calculateIncome(userProd.num, product.pricePrice)
});
}); });
}); });
return Array.from(userMap.values()); return result;
}, },
// //
totalAmount() { totalAmount() {
if (!this.tableData.length) { if (!this.allUserProdData.length) {
return '0.00'; return '0.0';
} }
return this.tableData.reduce((sum, row) => { return this.allUserProdData.reduce((sum, item) => {
return new Decimal(sum).plus(row.totalAmount || 0).toNumber(); return new Decimal(sum).plus(this.calculateIncome(item.num, item.pricePrice) || 0).toNumber();
}, 0).toFixed(2); }, 0).toFixed(1);
} }
}, },
watch: { watch: {
show: { show: {
handler(val) { handler(val) {
this.visible = val; this.visible = val;
if (val) {
this.handleSearch();
}
}, },
immediate: true immediate: true
}, },
@ -200,15 +237,156 @@ export default {
if (!val) { if (!val) {
this.$emit('update:show', false); this.$emit('update:show', false);
} }
},
allUserProdData: {
handler() {
this.handleSearch();
},
immediate: true
} }
}, },
methods: { methods: {
// //
calculateIncome(num, price) { calculateIncome(num, price) {
if (!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 {
} }
} }
.filter-container {
margin-bottom: 16px;
display: flex;
align-items: center;
}
:deep(.el-table) { :deep(.el-table) {
.process-header { .process-name {
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;
}
}
}
}
.prod-cell {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 4px;
.prod-num { .process-code {
color: #303133;
font-weight: 500;
.unit {
font-size: 12px;
color: #909399;
margin-left: 2px;
}
}
.prod-amount {
font-size: 12px; font-size: 12px;
color: #67c23a; color: #909399;
margin-top: 2px;
.unit {
margin-left: 2px;
}
} }
} }
.total-column { .user-info {
background-color: #fafafa; display: flex;
flex-direction: column;
.user-no {
font-size: 12px;
color: #909399;
margin-top: 2px;
}
} }
.total-income { .prod-num {
color: #409EFF; font-weight: 500;
color: #303133;
}
.prod-unit {
font-size: 12px;
color: #909399;
margin-left: 2px;
}
.prod-amount {
color: #67c23a;
font-weight: 500; font-weight: 500;
} }
} }
@ -327,21 +469,9 @@ export default {
// //
@media screen and (max-width: 1024px) { @media screen and (max-width: 1024px) {
.preview-container { .preview-container {
:deep(.el-table) { .summary-info {
.process-header { flex-direction: column;
.process-title { gap: 8px;
.process-name, .process-code {
text-align: center;
}
}
.process-info {
flex-direction: column;
align-items: center;
gap: 4px;
padding-top: 6px;
}
}
} }
} }
} }

View File

@ -92,7 +92,7 @@
<dict-tag :options="dict.type.report_status" :value="d.row[column.key]" size="mini"/> <dict-tag :options="dict.type.report_status" :value="d.row[column.key]" size="mini"/>
</template> </template>
<template v-else-if="column.key === 'totalAmount'"> <template v-else-if="column.key === 'totalAmount'">
{{d.row.totalAmount | dv}} {{d.row.totalAmount | fix1 | dv}}
</template> </template>
<template v-else-if="column.key === 'createTime'"> <template v-else-if="column.key === 'createTime'">
<template v-if="d.row.createTime">创建:{{d.row.createTime | dv}}({{d.row.createBy | dv}})<br/></template> <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 FormCol from "@/components/FormCol/index.vue";
import {DatePickerOptions, ReportStatus} from "@/utils/constants"; import {DatePickerOptions, ReportStatus} from "@/utils/constants";
import DeptSelect from '@/components/Business/Dept/DeptSelect.vue'; import DeptSelect from '@/components/Business/Dept/DeptSelect.vue';
import {toFixed} from '@/utils/index';
// //
const defaultSort = { const defaultSort = {
prop: "createTime", prop: "createTime",
@ -192,8 +192,8 @@ export default {
{key: 'deptName', visible: true, label: '部门', minWidth: null, sortable: true, overflow: false, align: 'center', width: null}, {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: '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: '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: false, overflow: false, align: 'center', width: null},
{key: 'productCount', 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: 'right', width: null},
{key: 'createTime', visible: true, label: '时间', minWidth: null, sortable: true, overflow: false, align: 'left', width: "250"}, {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}, {key: 'verifyRemark', visible: true, label: '审核意见', minWidth: null, sortable: false, overflow: true, align: 'center', width: null},
], ],
@ -274,7 +274,7 @@ export default {
return; return;
} }
if (column.property === 'totalAmount') { if (column.property === 'totalAmount') {
sums[index] = this.sum.totalAmount + ' 元'; sums[index] = toFixed(this.sum.totalAmount, 1) + ' 元';
} else { } else {
sums[index] = ''; sums[index] = '';
} }

View File

@ -144,7 +144,7 @@
{{d.row[column.key] | dv}} {{d.row.priceUnit | dv}} {{d.row[column.key] | dv}} {{d.row.priceUnit | dv}}
</template> </template>
<template v-else-if="['totalAmount'].includes(column.key)"> <template v-else-if="['totalAmount'].includes(column.key)">
{{d.row[column.key] | dv}} {{d.row[column.key] | fix1 | dv}}
</template> </template>
<template v-else-if="['pricePrice'].includes(column.key)"> <template v-else-if="['pricePrice'].includes(column.key)">
<template v-if="d.row.priceId"> <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 ReportUserProd from "@/views/yh/reportUserProd/index.vue";
import {calcMulDecimal} from "@/utils/money"; import {calcMulDecimal} from "@/utils/money";
import ReportUserProdDescriptions from "@/views/yh/reportProd/components/ReportUserProdDescriptions.vue"; 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 ReportOrderProdDescriptions from "@/views/yh/reportProd/components/ReportOrderProdDescriptions.vue";
import BooleanTag from '@/components/BooleanTag/index.vue' import BooleanTag from '@/components/BooleanTag/index.vue'
import {ReportStatus} from "@/utils/constants"; 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: '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: '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: '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: '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: 'center', 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: '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: '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}, {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') { if (column.property === 'num') {
sums[index] = this.sum.num; sums[index] = this.sum.num;
} else if (column.property === 'totalAmount') { } else if (column.property === 'totalAmount') {
sums[index] = this.sum.totalAmount + ' 元'; sums[index] = toFixed(this.sum.totalAmount, 1) + ' 元';
} else { } else {
sums[index] = ''; sums[index] = '';
} }

View File

@ -165,7 +165,7 @@
{{d.row[column.key] | dv}} {{ d.row.priceUnit | dv}} {{d.row[column.key] | dv}} {{ d.row.priceUnit | dv}}
</template> </template>
<template v-else-if="column.key === 'totalPrice'"> <template v-else-if="column.key === 'totalPrice'">
{{d.row.totalPrice | fix2 | dv}} {{d.row.totalPrice | fix1 | dv}}
</template> </template>
<template v-else-if="column.key === 'reportStatus'"> <template v-else-if="column.key === 'reportStatus'">
<dict-tag :value="d.row.reportStatus" :options="dict.type.report_status" size="mini"/> <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 DeptSelect from '@/components/Business/Dept/DeptSelect.vue';
import {dashboardUserProd} from '@/api/yh/dashboard.js'; import {dashboardUserProd} from '@/api/yh/dashboard.js';
import {getReportUserProdSum} from '@/api/dashboard/reportUserProd'; import {getReportUserProdSum} from '@/api/dashboard/reportUserProd';
import {toFixed} from '@/utils/index';
// //
const defaultSort = { const defaultSort = {
@ -358,7 +359,7 @@ export default {
return; return;
} }
if (column.property === 'totalPrice') { if (column.property === 'totalPrice') {
sums[index] = this.sum.totalAmount + ' 元'; sums[index] = toFixed(this.sum.totalAmount, 1) + ' 元';
} else if (column.property === 'num') { } else if (column.property === 'num') {
sums[index] = this.sum.num; sums[index] = this.sum.num;
} else { } else {