<template>
|
<div class="app-container">
|
<div class="content-layout">
|
<!-- 左侧台账 + 顶部筛选 -->
|
<div class="left-panel">
|
<div class="left-header">
|
<!-- <div class="left-title">生产台账</div> -->
|
<el-radio-group v-model="dateType" size="small" @change="handleDateTypeChange">
|
<el-radio-button label="day">日</el-radio-button>
|
<el-radio-button label="month">月</el-radio-button>
|
</el-radio-group>
|
|
</div>
|
<PIMTable
|
rowKey="id"
|
:column="leftTableColumn"
|
:tableData="leftTableData"
|
:tableLoading="tableLoading"
|
:page="page"
|
:height="200"
|
@row-click="handleLeftRowClick"
|
@pagination="pagination"
|
></PIMTable>
|
</div>
|
|
<!-- 右侧明细(原有内容) -->
|
<div class="right-panel">
|
<div class="header-filters">
|
<el-button @click="handleOut" class="ml10">导出</el-button>
|
</div>
|
<PIMTable
|
rowKey="id"
|
:column="tableColumn"
|
:tableData="tableData"
|
:page="page1"
|
:tableLoading="tableLoading"
|
style="margin-right: 20px;"
|
@pagination="pagination1"
|
></PIMTable>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup>
|
import {onMounted, ref} from "vue";
|
import { ElMessageBox } from "element-plus";
|
import dayjs from "dayjs";
|
import {salesLedgerProductionAccountingListProductionDetails, salesLedgerProductionAccountingList} from "@/api/productionManagement/productionCosting.js";
|
const { proxy } = getCurrentInstance();
|
|
const tableColumn = ref([
|
{
|
label: "生产日期",
|
prop: "scheduleDate",
|
minWidth: 100,
|
},
|
{
|
label: "生产人",
|
prop: "schedulingUserName",
|
minWidth: 100,
|
},
|
{
|
label: "合同号",
|
prop: "salesContractNo",
|
minWidth: 100,
|
},
|
{
|
label: "客户名称",
|
prop: "customerName",
|
minWidth: 100,
|
},
|
{
|
label: "产品大类",
|
prop: "productName",
|
minWidth: 100,
|
},
|
{
|
label: "规格型号",
|
prop: "productModelName",
|
minWidth: 100,
|
},
|
{
|
label: "单位",
|
prop: "unit",
|
minWidth: 100,
|
},
|
{
|
label: "工序",
|
prop: "process",
|
minWidth: 100,
|
},
|
{
|
label: "生产数量",
|
prop: "quantity",
|
minWidth: 100,
|
},
|
{
|
label: "工时定额",
|
prop: "workHours",
|
minWidth: 100,
|
},
|
{
|
label: "工资",
|
prop: "wages",
|
minWidth: 100,
|
},
|
]);
|
|
// 左侧汇总台账列(生产人、产量、工资、合格率)
|
const leftTableColumn = ref([
|
{
|
label: "生产人",
|
prop: "schedulingUserName",
|
minWidth: 100,
|
},
|
{
|
label: "产量",
|
prop: "outputNum",
|
minWidth: 100,
|
|
},
|
{
|
label: "工资",
|
prop: "wages",
|
minWidth: 100,
|
|
},
|
{
|
label: "合格率",
|
prop: "outputRate",
|
minWidth: 100,
|
|
},
|
]);
|
|
const tableData = ref([]);
|
const tableLoading = ref(false);
|
const tableLoading1 = ref(false);
|
const leftTableData = ref([]);
|
// 日 / 月 切换(默认按日)
|
const dateType = ref("day");
|
const page = reactive({
|
current: 1,
|
size: 100,
|
total: 0,
|
});
|
|
const page1 = reactive({
|
current: 1,
|
size: 100,
|
total: 0,
|
});
|
|
const data = reactive({
|
searchForm: {
|
schedulingUserName: "",
|
salesContractNo: "",
|
entryDate: [
|
dayjs().format("YYYY-MM-DD"),
|
dayjs().add(1, "day").format("YYYY-MM-DD"),
|
], // 录入日期
|
entryDateStart: dayjs().format("YYYY-MM-DD"),
|
entryDateEnd: dayjs().add(1, "day").format("YYYY-MM-DD"),
|
},
|
});
|
const { searchForm } = toRefs(data);
|
|
const pagination = (obj) => {
|
page.current = obj.page;
|
page.size = obj.limit;
|
getList();
|
};
|
|
const pagination1 = (obj) => {
|
page1.current = obj.page;
|
page1.size = obj.limit;
|
getList1();
|
};
|
|
const changeDaterange = (value) => {
|
if (value) {
|
searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
|
searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
|
} else {
|
searchForm.value.entryDateStart = undefined;
|
searchForm.value.entryDateEnd = undefined;
|
}
|
handleQuery();
|
};
|
const getList = () => {
|
tableLoading.value = true;
|
const params = { ...searchForm.value, ...page };
|
params.dateType = dateType.value;
|
params.entryDate = undefined
|
|
salesLedgerProductionAccountingList(params).then((res) => {
|
tableLoading.value = false;
|
const records = res.data.records || [];
|
leftTableData.value = records;
|
page.total = res.data.total || 0;
|
});
|
|
};
|
|
const getList1 = () => {
|
tableLoading1.value = true;
|
const params = { ...page1, ...searchForm.value };
|
salesLedgerProductionAccountingListProductionDetails(params).then((res) => {
|
tableLoading1.value = false;
|
tableData.value = res.data.records || [];;
|
page1.total = res.data.total || 0;
|
});
|
};
|
|
// 构建左侧汇总台账(按生产人汇总产量、工资等)
|
const buildLeftTableData = (records) => {
|
const map = {};
|
records.forEach((item) => {
|
const key = item.schedulingUserName || "未知";
|
if (!map[key]) {
|
map[key] = {
|
id: key,
|
schedulingUserName: key,
|
finishedNum: 0,
|
wages: 0,
|
qualifiedRate: item.qualifiedRate ?? null,
|
};
|
}
|
map[key].finishedNum += Number(item.finishedNum || 0);
|
map[key].wages += Number(item.wages || 0);
|
if (item.qualifiedRate != null) {
|
map[key].qualifiedRate = item.qualifiedRate;
|
}
|
});
|
leftTableData.value = Object.values(map);
|
};
|
|
// 左侧日/月切换
|
const handleDateTypeChange = () => {
|
// 这里只作为筛选条件的一部分,直接重新查询列表
|
page.current = 1;
|
getList();
|
handleQuery()
|
};
|
|
// 点击左侧行,刷右侧明细(按生产人过滤)
|
const handleLeftRowClick = (row) => {
|
searchForm.value.schedulingUserName = row.schedulingUserName || "";
|
handleQuery();
|
};
|
|
// 查询列表
|
/** 搜索按钮操作 */
|
const handleQuery = () => {
|
page1.current = 1;
|
getList1();
|
};
|
|
|
// 导出
|
const handleOut = () => {
|
ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
proxy.download("/salesLedger/productionAccounting/export", {}, "生产核算.xlsx");
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
onMounted(() => {
|
getList();
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.content-layout {
|
display: flex;
|
flex-direction: column;
|
gap: 16px;
|
}
|
|
.left-panel {
|
flex: 0 0 50%;
|
display: flex;
|
flex-direction: column;
|
gap: 10px;
|
}
|
|
.right-panel {
|
flex: 0 0 50%;
|
display: flex;
|
flex-direction: column;
|
gap: 10px;
|
}
|
|
.left-header {
|
display: flex;
|
align-items: center;
|
gap: 12px;
|
margin-bottom: 8px;
|
}
|
|
.left-title {
|
font-size: 16px;
|
color: #ffffff;
|
}
|
|
.header-filters {
|
display: flex;
|
align-items: center;
|
flex: 1;
|
justify-content: flex-end;
|
gap: 8px;
|
}
|
|
.search_title {
|
color: #ffffff;
|
}
|
|
.ml10 {
|
margin-left: 10px;
|
}
|
</style>
|