部门模块功能开发
This commit is contained in:
parent
5c2b4c1bc3
commit
1b98e2da99
|
|
@ -0,0 +1,822 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 查询表单部分保持不变 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="90px">
|
||||
<!-- 库存日期 -->
|
||||
<el-form-item label="库存日期">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
type="daterange"
|
||||
align="right"
|
||||
unlink-panels
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
format="yyyy-MM-dd"
|
||||
value-format="yyyy-MM-dd"
|
||||
style="width: 240px"
|
||||
:picker-options="pickerOptions">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 货品类别 - 级联多选 -->
|
||||
<el-form-item label="货品类别">
|
||||
<el-cascader
|
||||
v-model="selectedCategories"
|
||||
:options="goodsCategoryOptions"
|
||||
:show-all-levels="false"
|
||||
:props="categoryProps"
|
||||
clearable
|
||||
filterable
|
||||
multiple
|
||||
collapse-tags
|
||||
placeholder="请选择货品类别"
|
||||
style="width: 200px;"
|
||||
@change="handleCategoryChange">
|
||||
</el-cascader>
|
||||
|
||||
</el-form-item>
|
||||
|
||||
<!-- 所属区域 -->
|
||||
<el-form-item label="所属区域">
|
||||
<el-cascader
|
||||
v-model="selectedOrg"
|
||||
:options="orgOptions"
|
||||
:show-all-levels="false"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="请选择所属区域"
|
||||
:props="{
|
||||
checkStrictly: true,
|
||||
expandTrigger: 'hover',
|
||||
value: 'orgId',
|
||||
label: 'orgName',
|
||||
children: 'children'
|
||||
}"
|
||||
style="width: 200px;"
|
||||
@change="handleAreaChange">
|
||||
</el-cascader>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 货品仓库 -->
|
||||
<el-form-item label="货品仓库" prop="warehouseId">
|
||||
<el-select
|
||||
v-model="queryParams.warehouseIdList"
|
||||
multiple
|
||||
placeholder="请选择货品仓库"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@change="handleWarehouseChange">
|
||||
<el-option
|
||||
v-for="item in wareHouseOptions"
|
||||
:key="item.warehouseId"
|
||||
:label="item.warehouseName"
|
||||
:value="item.warehouseId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 货品名称 -->
|
||||
<el-form-item label="货品名称" prop="goodsName">
|
||||
<el-input
|
||||
v-model="queryParams.materialName"
|
||||
placeholder="请输入货品名称"
|
||||
maxlength="100"
|
||||
clearable
|
||||
style="width: 200px"/>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作按钮栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="info"
|
||||
plain
|
||||
icon="el-icon-printer"
|
||||
size="mini"
|
||||
@click="handlePrint"
|
||||
>打印</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 数据表格 - 只修改字段名称以匹配后端实体 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="tableListData"
|
||||
border
|
||||
show-summary
|
||||
:summary-method="getSummaries">
|
||||
<el-table-column label="序号" align="center" width="60" type="index">
|
||||
<template slot-scope="scope">
|
||||
<span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 货品编码 -->
|
||||
<el-table-column label="货品编码" align="center" prop="materialCode" width="120" :show-overflow-tooltip="true"/>
|
||||
<!-- 货品名称 -->
|
||||
<el-table-column label="货品名称" align="center" prop="materialName" width="150" :show-overflow-tooltip="true"/>
|
||||
<!-- 货品类别 -->
|
||||
<el-table-column label="货品类别" align="center" prop="categoryName" width="120" :show-overflow-tooltip="true"/>
|
||||
<!-- 计量单位 -->
|
||||
<el-table-column label="计量单位" align="center" prop="unitName" width="100"/>
|
||||
<!-- 货品规格 -->
|
||||
<el-table-column label="货品规格" align="center" prop="size" width="120" :show-overflow-tooltip="true"/>
|
||||
<!-- 所属区域 -->
|
||||
<el-table-column label="所属区域" align="center" prop="areaName" width="120" :show-overflow-tooltip="true"/>
|
||||
<!-- 所属仓库 -->
|
||||
<el-table-column label="所属仓库" align="center" prop="warehouseName" width="120" :show-overflow-tooltip="true"/>
|
||||
<!-- 入库数量 -->
|
||||
<el-table-column label="入库数量" align="center" prop="intoTotalNum" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatNumber(scope.row.intoTotalNum) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 入库金额(元) -->
|
||||
<el-table-column label="入库金额(元)" align="center" prop="intoTotalAmount" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatMoney((scope.row.intoTotalAmount || 0) / 100) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 入库总数量 -->
|
||||
<el-table-column label="入库总数量" align="center" prop="intoTotalNum" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatNumber(scope.row.intoTotalNum) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 入库总金额(元) -->
|
||||
<el-table-column label="入库总金额(元)" align="center" prop="intoTotalAmount" width="130">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatMoney((scope.row.intoTotalAmount || 0) / 100) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 出库数量 -->
|
||||
<el-table-column label="出库数量" align="center" prop="outTotalNum" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatNumber(scope.row.outTotalNum) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 出库金额(元) -->
|
||||
<el-table-column label="出库金额(元)" align="center" prop="outTotalAmount" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatMoney((scope.row.outTotalAmount || 0) / 100) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 出库总数量 -->
|
||||
<el-table-column label="出库总数量" align="center" prop="outTotalNum" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatNumber(scope.row.outTotalNum) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 出库总金额(元) -->
|
||||
<el-table-column label="出库总金额(元)" align="center" prop="outTotalAmount" width="130">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatMoney((scope.row.outTotalAmount || 0) / 100) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 导入区域树API
|
||||
import {getTreeArea} from "@/api/canteen/canteenRecord";
|
||||
// 导入库存入库相关API
|
||||
import {
|
||||
listInventoryIntoDetail,
|
||||
exportInventoryIntoDetail,
|
||||
getWarehouseList,
|
||||
getGoodsCategoryDict
|
||||
} from "@/api/report/inventoryhz";
|
||||
|
||||
export default {
|
||||
name: "InventoryIntoDetail",
|
||||
dicts: [],
|
||||
data() {
|
||||
return {
|
||||
// 合计数据
|
||||
summaryData: null,
|
||||
|
||||
// 区域树选项
|
||||
orgOptions: [],
|
||||
selectedOrg: [], // 选中的区域
|
||||
|
||||
// 货品类别相关数据
|
||||
goodsCategoryOptions: [], // 货品类别树形数据
|
||||
selectedCategories: [], // 选中的货品类别路径数组
|
||||
categoryProps: {
|
||||
expandTrigger: 'hover',
|
||||
value: 'id',
|
||||
label: 'dictLabel',
|
||||
children: 'children',
|
||||
emitPath: true,
|
||||
multiple: true
|
||||
},
|
||||
|
||||
// 仓库下拉选项
|
||||
wareHouseOptions: [],
|
||||
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
|
||||
// 总条数
|
||||
total: 0,
|
||||
|
||||
// 表格数据
|
||||
tableListData: [],
|
||||
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
recordId: null, // 单据编号
|
||||
categoryIdList: [], // 货品类别ID列表(包含所有子节点)
|
||||
warehouseIdList: [], // 仓库ID列表
|
||||
goodsName: null, // 货品名称
|
||||
areaIdList: [], // 区域ID列表
|
||||
startDate: null, // 开始日期
|
||||
endDate: null // 结束日期
|
||||
},
|
||||
|
||||
// 日期范围
|
||||
dateRange: this.defaultDateRange(),
|
||||
|
||||
// 日期选择器快捷选项
|
||||
pickerOptions: {
|
||||
shortcuts: [{
|
||||
text: '最近一周',
|
||||
onClick: (picker) => {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 6);
|
||||
picker.$emit('pick', [this.formatDate(start), this.formatDate(end)]);
|
||||
}
|
||||
}, {
|
||||
text: '最近一个月',
|
||||
onClick: (picker) => {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
|
||||
picker.$emit('pick', [this.formatDate(start), this.formatDate(end)]);
|
||||
}
|
||||
}, {
|
||||
text: '最近三个月',
|
||||
onClick: (picker) => {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 91);
|
||||
picker.$emit('pick', [this.formatDate(start), this.formatDate(end)]);
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 初始化数据
|
||||
this.getTree(); // 获取区域树
|
||||
this.getWareHouseData(); // 获取仓库列表
|
||||
this.getGoodsCategoryData(); // 获取货品类别树
|
||||
this.getList(); // 获取列表数据
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 自定义合计计算方法
|
||||
*/
|
||||
getSummaries(param) {
|
||||
const { columns, data } = param;
|
||||
const sums = [];
|
||||
|
||||
columns.forEach((column, index) => {
|
||||
if (index === 0) {
|
||||
// 第一列显示"合计"
|
||||
sums[index] = '合计';
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据列名判断需要合计的字段
|
||||
const columnProp = column.property;
|
||||
if (this.summaryData) {
|
||||
switch(columnProp) {
|
||||
case 'intoTotalNum':
|
||||
sums[index] = this.formatNumber(this.summaryData.intoTotalNum || 0);
|
||||
break;
|
||||
case 'intoTotalAmount':
|
||||
sums[index] = this.formatMoney((this.summaryData.intoTotalAmount || 0) / 100);
|
||||
break;
|
||||
case 'outTotalNum':
|
||||
sums[index] = this.formatNumber(this.summaryData.outTotalNum || 0);
|
||||
break;
|
||||
case 'outTotalAmount':
|
||||
sums[index] = this.formatMoney((this.summaryData.outTotalAmount || 0) / 100);
|
||||
break;
|
||||
default:
|
||||
// 其他列显示空
|
||||
sums[index] = '';
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sums[index] = '';
|
||||
}
|
||||
});
|
||||
|
||||
return sums;
|
||||
},
|
||||
|
||||
// 保持其他方法不变
|
||||
getGoodsCategoryData() {
|
||||
getGoodsCategoryDict().then((response) => {
|
||||
const data = response.data || response || [];
|
||||
console.log('获取到的货品类别数据:', data);
|
||||
|
||||
// 如果后端返回的是平铺数据,需要转换为树形结构
|
||||
if (data.length > 0 && !data[0].children) {
|
||||
// 使用我们自己的构建树方法
|
||||
this.goodsCategoryOptions = this.buildCategoryTree(data);
|
||||
} else {
|
||||
// 如果已经是树形结构,直接使用
|
||||
this.goodsCategoryOptions = data;
|
||||
}
|
||||
|
||||
console.log('转换后的货品类别树:', this.goodsCategoryOptions);
|
||||
}).catch(error => {
|
||||
console.error('获取货品类别失败:', error);
|
||||
this.goodsCategoryOptions = [];
|
||||
});
|
||||
},
|
||||
|
||||
buildCategoryTree(list) {
|
||||
// 创建根节点(原料和商品)
|
||||
const tree = [];
|
||||
|
||||
// 1. 原料根节点
|
||||
const materialRoot = {
|
||||
id: 25595457052610560,
|
||||
dictLabel: "原料",
|
||||
parentId: -1,
|
||||
children: []
|
||||
};
|
||||
|
||||
// 2. 商品根节点
|
||||
const goodsRoot = {
|
||||
id: 65595542415085568,
|
||||
dictLabel: "商品",
|
||||
parentId: -1,
|
||||
children: []
|
||||
};
|
||||
|
||||
// 将数据按 parent_id 分组
|
||||
const map = {};
|
||||
list.forEach(item => {
|
||||
if (!map[item.id]) {
|
||||
map[item.id] = { ...item, children: [] };
|
||||
}
|
||||
});
|
||||
|
||||
// 构建树结构
|
||||
list.forEach(item => {
|
||||
if (item.parentId === 25595457052610560) {
|
||||
const child = { ...item, children: [] };
|
||||
materialRoot.children.push(child);
|
||||
map[item.id] = child;
|
||||
} else if (item.parentId === 65595542415085568) {
|
||||
const child = { ...item, children: [] };
|
||||
goodsRoot.children.push(child);
|
||||
map[item.id] = child;
|
||||
} else if (item.parentId !== -1 && map[item.parentId]) {
|
||||
const child = { ...item, children: [] };
|
||||
if (!map[item.parentId].children) {
|
||||
map[item.parentId].children = [];
|
||||
}
|
||||
map[item.parentId].children.push(child);
|
||||
map[item.id] = child;
|
||||
}
|
||||
});
|
||||
|
||||
tree.push(materialRoot, goodsRoot);
|
||||
return tree;
|
||||
},
|
||||
|
||||
handleCategoryChange(values) {
|
||||
if (!values || values.length === 0) {
|
||||
this.queryParams.categoryIdList = [];
|
||||
return;
|
||||
}
|
||||
let allCategoryIds = [];
|
||||
values.forEach(path => {
|
||||
const selectedId = path[path.length - 1];
|
||||
const node = this.findCategoryNodeById(selectedId, this.goodsCategoryOptions);
|
||||
if (node) {
|
||||
allCategoryIds.push(...this.getAllChildCategoryIds(node));
|
||||
}
|
||||
});
|
||||
|
||||
this.queryParams.categoryIdList = Array.from(new Set(allCategoryIds));
|
||||
|
||||
console.log("最终传给后台的 categoryIdList =", this.queryParams.categoryIdList);
|
||||
},
|
||||
|
||||
findCategoryNodeById(id, options) {
|
||||
for (const node of options) {
|
||||
if (node.id === id) {
|
||||
return node;
|
||||
}
|
||||
if (node.children && node.children.length > 0) {
|
||||
const found = this.findCategoryNodeById(id, node.children);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
getAllChildCategoryIds(node) {
|
||||
if (!node) return [];
|
||||
|
||||
let ids = [node.id];
|
||||
|
||||
if (node.children && node.children.length > 0) {
|
||||
node.children.forEach(child => {
|
||||
ids = ids.concat(this.getAllChildCategoryIds(child));
|
||||
});
|
||||
}
|
||||
|
||||
return ids;
|
||||
},
|
||||
|
||||
getSelectedOrgIds() {
|
||||
if (!this.selectedOrg || this.selectedOrg.length === 0) return [];
|
||||
const lastValue = this.selectedOrg[this.selectedOrg.length - 1];
|
||||
// 找到对应节点
|
||||
let stack = [...this.orgOptions];
|
||||
let node = null;
|
||||
for (let val of this.selectedOrg) {
|
||||
node = stack.find(item => item.orgId === val);
|
||||
if (!node) break;
|
||||
stack = node.children || [];
|
||||
}
|
||||
|
||||
if (node) {
|
||||
return this.getAllChildIds(node, this.orgOptions);
|
||||
}
|
||||
return [lastValue];
|
||||
},
|
||||
|
||||
getAllChildIds(node, options) {
|
||||
let ids = [node.orgId]; // 当前节点
|
||||
if (node.children && node.children.length > 0) {
|
||||
node.children.forEach(child => {
|
||||
ids = ids.concat(this.getAllChildIds(child, options)); // 递归获取子节点
|
||||
});
|
||||
}
|
||||
return ids;
|
||||
},
|
||||
|
||||
getTree() {
|
||||
getTreeArea().then(res => {
|
||||
this.orgOptions = res || [];
|
||||
});
|
||||
},
|
||||
|
||||
handleAreaChange() {
|
||||
// 区域变化时,重新加载仓库列表
|
||||
this.queryParams.warehouseIdList = [];
|
||||
this.getWareHouseData();
|
||||
},
|
||||
|
||||
handleWarehouseChange() {
|
||||
// 可以在这里添加其他逻辑
|
||||
},
|
||||
|
||||
getWareHouseData() {
|
||||
const areaIdList = this.getSelectedOrgIds();
|
||||
|
||||
console.log("选中的 orgId 列表:", areaIdList, Array.isArray(areaIdList));
|
||||
|
||||
if (!areaIdList || !areaIdList.length) {
|
||||
this.wareHouseOptions = [];
|
||||
return;
|
||||
}
|
||||
getWarehouseList({
|
||||
areaIdList: areaIdList.join(',')
|
||||
}).then(res => {
|
||||
this.wareHouseOptions = res.data || [];
|
||||
});
|
||||
},
|
||||
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
resetQuery() {
|
||||
this.dateRange = this.defaultDateRange();
|
||||
this.selectedOrg = [];
|
||||
this.selectedCategories = [];
|
||||
this.summaryData = null;
|
||||
this.queryParams = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
recordId: null,
|
||||
categoryIdList: [],
|
||||
warehouseIdList: [],
|
||||
goodsName: null,
|
||||
areaIdList: [],
|
||||
startDate: null,
|
||||
endDate: null
|
||||
};
|
||||
this.resetForm("queryForm");
|
||||
this.getWareHouseData();
|
||||
this.handleQuery();
|
||||
},
|
||||
|
||||
getList() {
|
||||
this.loading = true;
|
||||
|
||||
// 获取选中的区域ID列表
|
||||
this.queryParams.areaIdList = this.getSelectedOrgIds();
|
||||
|
||||
// 处理日期范围
|
||||
if (this.dateRange && this.dateRange.length === 2) {
|
||||
this.queryParams.startDate = this.dateRange[0];
|
||||
this.queryParams.endDate = this.dateRange[1];
|
||||
} else {
|
||||
this.queryParams.startDate = null;
|
||||
this.queryParams.endDate = null;
|
||||
}
|
||||
// 调用API查询
|
||||
listInventoryIntoDetail(this.queryParams).then(response => {
|
||||
const data = response.data || response;
|
||||
this.tableListData = data.rows || [];
|
||||
this.total = Number(data.total) || 0;
|
||||
this.summaryData = data.summary || null;
|
||||
console.log('合计数据:', this.summaryData);
|
||||
this.loading = false;
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
|
||||
handleExport() {
|
||||
// 处理日期范围
|
||||
let startDate = '';
|
||||
let endDate = '';
|
||||
|
||||
if (this.dateRange && this.dateRange.length === 2) {
|
||||
const start = this.dateRange[0];
|
||||
const end = this.dateRange[1];
|
||||
|
||||
startDate = start + ' 00:00:00';
|
||||
endDate = end + ' 23:59:59';
|
||||
}
|
||||
|
||||
// 构建参数
|
||||
let param = {
|
||||
pageNum: this.queryParams.pageNum,
|
||||
pageSize: this.queryParams.pageSize,
|
||||
recordId: this.queryParams.recordId,
|
||||
categoryIdList: this.queryParams.categoryIdList,
|
||||
warehouseIdList: this.queryParams.warehouseIdList,
|
||||
materialName: this.queryParams.materialName,
|
||||
areaIdList: this.getSelectedOrgIds(),
|
||||
startDate: startDate,
|
||||
endDate: endDate
|
||||
};
|
||||
|
||||
// 使用download方法(参考另一个模块)
|
||||
this.$modal.confirm('是否确认导出货品汇总明细数据项?').then(() => {
|
||||
this.loading = true;
|
||||
|
||||
// 使用download方法
|
||||
this.download(
|
||||
'/smart-canteen/drp/inventoryIntohz/goods/summary/export',
|
||||
param,
|
||||
`货品库存明细_${new Date().getTime()}.xlsx`
|
||||
).then(() => {
|
||||
this.loading = false;
|
||||
this.$modal.msgSuccess("导出成功");
|
||||
}).catch(error => {
|
||||
this.loading = false;
|
||||
console.error('导出失败:', error);
|
||||
this.$modal.msgError("导出失败");
|
||||
});
|
||||
}).catch(() => {
|
||||
// 用户取消
|
||||
});
|
||||
},
|
||||
|
||||
handlePrint() {
|
||||
const printData = {
|
||||
title: '库存入库明细表',
|
||||
columns: [
|
||||
{ prop: 'materialCode', label: '货品编码', width: 120 },
|
||||
{ prop: 'materialName', label: '货品名称', width: 150 },
|
||||
{ prop: 'categoryName', label: '货品类别', width: 120 },
|
||||
{ prop: 'unitName', label: '计量单位', width: 100 },
|
||||
{ prop: 'size', label: '货品规格', width: 120 },
|
||||
{ prop: 'areaName', label: '所属区域', width: 120 },
|
||||
{ prop: 'warehouseName', label: '所属仓库', width: 120 },
|
||||
{ prop: 'intoTotalNum', label: '入库数量', width: 100 },
|
||||
{ prop: 'intoTotalAmount', label: '入库金额(元)', width: 120 },
|
||||
{ prop: 'intoTotalNum', label: '入库总数量', width: 120 },
|
||||
{ prop: 'intoTotalAmount', label: '入库总金额(元)', width: 130 },
|
||||
{ prop: 'outTotalNum', label: '出库数量', width: 100 },
|
||||
{ prop: 'outTotalAmount', label: '出库金额(元)', width: 120 },
|
||||
{ prop: 'outTotalNum', label: '出库总数量', width: 120 },
|
||||
{ prop: 'outTotalAmount', label: '出库总金额(元)', width: 130 }
|
||||
],
|
||||
data: this.tableListData,
|
||||
queryParams: this.queryParams
|
||||
};
|
||||
|
||||
const printWindow = window.open('', '_blank');
|
||||
const printContent = this.generatePrintHTML(printData);
|
||||
printWindow.document.write(printContent);
|
||||
printWindow.document.close();
|
||||
printWindow.focus();
|
||||
setTimeout(() => {
|
||||
printWindow.print();
|
||||
printWindow.close();
|
||||
}, 500);
|
||||
},
|
||||
|
||||
generatePrintHTML(printData) {
|
||||
let html = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>${printData.title}</title>
|
||||
<style>
|
||||
body { font-family: "Microsoft YaHei", Arial, sans-serif; margin: 20px; }
|
||||
h2 { text-align: center; margin-bottom: 20px; }
|
||||
table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
||||
th, td { border: 1px solid #000; padding: 8px; text-align: center; }
|
||||
th { background-color: #f0f0f0; font-weight: bold; }
|
||||
.print-info { margin-bottom: 20px; font-size: 12px; }
|
||||
@media print {
|
||||
@page { size: landscape; margin: 10mm; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>${printData.title}</h2>
|
||||
<div class="print-info">
|
||||
<p>打印时间:${new Date().toLocaleString()}</p>
|
||||
<p>共 ${printData.data.length} 条记录</p>
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
`;
|
||||
|
||||
printData.columns.forEach(col => {
|
||||
html += `<th>${col.label}</th>`;
|
||||
});
|
||||
|
||||
html += `
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
`;
|
||||
|
||||
printData.data.forEach(row => {
|
||||
html += '<tr>';
|
||||
printData.columns.forEach(col => {
|
||||
let value = row[col.prop] || '-';
|
||||
if (col.prop === 'intoTotalAmount' || col.prop === 'outTotalAmount') {
|
||||
value = this.formatMoney((value || 0) / 100);
|
||||
} else if (col.prop === 'intoTotalNum' || col.prop === 'outTotalNum') {
|
||||
value = this.formatNumber(value);
|
||||
}
|
||||
html += `<td>${value}</td>`;
|
||||
});
|
||||
html += '</tr>';
|
||||
});
|
||||
|
||||
html += `
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
return html;
|
||||
},
|
||||
|
||||
defaultDateRange() {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 30 * 24 * 60 * 60 * 1000);
|
||||
return [this.formatDate(start), this.formatDate(end)];
|
||||
},
|
||||
|
||||
formatDate(date) {
|
||||
if (!date) return '';
|
||||
const d = new Date(date);
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
},
|
||||
|
||||
formatDateTime(date) {
|
||||
if (!date) return '';
|
||||
const d = new Date(date);
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getDate()).padStart(2, '0');
|
||||
const hours = String(d.getHours()).padStart(2, '0');
|
||||
const minutes = String(d.getMinutes()).padStart(2, '0');
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
},
|
||||
|
||||
formatMoney(value) {
|
||||
if (value === null || value === undefined || value === '') return '0.00';
|
||||
return Number(value).toFixed(2);
|
||||
},
|
||||
|
||||
formatNumber(value) {
|
||||
if (value === null || value === undefined || value === '') return '0';
|
||||
return Number(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* 合计行样式增强 */
|
||||
::v-deep .el-table__footer-wrapper tbody td {
|
||||
background-color: #f5f7fa;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
::v-deep .el-table__footer-wrapper tbody td:first-child {
|
||||
font-weight: bold;
|
||||
color: #409EFF;
|
||||
}
|
||||
|
||||
/* 表格样式 */
|
||||
::v-deep .el-table__fixed-right td.blue-record-col .cell {
|
||||
color: #1677ff !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 调整表单样式 */
|
||||
::v-deep .el-form-item {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
/* 调整按钮样式 */
|
||||
::v-deep .el-button {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item__content {
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
/* 调整表格样式 */
|
||||
::v-deep .el-table {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
::v-deep .el-table th {
|
||||
background-color: #f5f7fa;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
::v-deep .el-pagination {
|
||||
margin-top: 15px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,800 @@
|
|||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 查询表单部分保持不变 -->
|
||||
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="90px">
|
||||
<!-- 库存日期 -->
|
||||
<el-form-item label="库存日期">
|
||||
<el-date-picker
|
||||
v-model="dateRange"
|
||||
type="daterange"
|
||||
align="right"
|
||||
unlink-panels
|
||||
range-separator="至"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
format="yyyy-MM-dd"
|
||||
value-format="yyyy-MM-dd"
|
||||
style="width: 240px"
|
||||
:picker-options="pickerOptions">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 货品类别 - 级联多选 -->
|
||||
<el-form-item label="货品类别">
|
||||
<el-cascader
|
||||
v-model="selectedCategories"
|
||||
:options="goodsCategoryOptions"
|
||||
:show-all-levels="false"
|
||||
:props="categoryProps"
|
||||
clearable
|
||||
filterable
|
||||
multiple
|
||||
collapse-tags
|
||||
placeholder="请选择货品类别"
|
||||
style="width: 200px;"
|
||||
@change="handleCategoryChange">
|
||||
</el-cascader>
|
||||
|
||||
</el-form-item>
|
||||
|
||||
<!-- 所属区域 -->
|
||||
<el-form-item label="所属区域">
|
||||
<el-cascader
|
||||
v-model="selectedOrg"
|
||||
:options="orgOptions"
|
||||
:show-all-levels="false"
|
||||
clearable
|
||||
filterable
|
||||
placeholder="请选择所属区域"
|
||||
:props="{
|
||||
checkStrictly: true,
|
||||
expandTrigger: 'hover',
|
||||
value: 'orgId',
|
||||
label: 'orgName',
|
||||
children: 'children'
|
||||
}"
|
||||
style="width: 200px;"
|
||||
@change="handleAreaChange">
|
||||
</el-cascader>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 货品仓库 -->
|
||||
<el-form-item label="货品仓库" prop="warehouseId">
|
||||
<el-select
|
||||
v-model="queryParams.warehouseIdList"
|
||||
multiple
|
||||
placeholder="请选择货品仓库"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
@change="handleWarehouseChange">
|
||||
<el-option
|
||||
v-for="item in wareHouseOptions"
|
||||
:key="item.warehouseId"
|
||||
:label="item.warehouseName"
|
||||
:value="item.warehouseId">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<!-- 操作按钮栏 -->
|
||||
<el-row :gutter="10" class="mb8">
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="warning"
|
||||
plain
|
||||
icon="el-icon-download"
|
||||
size="mini"
|
||||
@click="handleExport"
|
||||
>导出</el-button>
|
||||
</el-col>
|
||||
<el-col :span="1.5">
|
||||
<el-button
|
||||
type="info"
|
||||
plain
|
||||
icon="el-icon-printer"
|
||||
size="mini"
|
||||
@click="handlePrint"
|
||||
>打印</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
<!-- 数据表格 - 只修改字段名称以匹配后端实体 -->
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="tableListData"
|
||||
border
|
||||
show-summary
|
||||
:summary-method="getSummaries">
|
||||
<el-table-column label="序号" align="center" width="60" type="index">
|
||||
<template slot-scope="scope">
|
||||
<span>{{(queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 货品类别 -->
|
||||
<el-table-column label="货品类别" align="center" prop="categoryName" width="120" :show-overflow-tooltip="true"/>
|
||||
<!-- 所属区域 -->
|
||||
<el-table-column label="所属区域" align="center" prop="areaName" :show-overflow-tooltip="true"/>
|
||||
<!-- 所属仓库 -->
|
||||
<el-table-column label="所属仓库" align="center" prop="warehouseName" :show-overflow-tooltip="true"/>
|
||||
<!-- 入库数量 -->
|
||||
<el-table-column label="入库数量" align="center" prop="intoTotalNum" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatNumber(scope.row.intoTotalNum) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 入库金额(元) -->
|
||||
<el-table-column label="入库金额(元)" align="center" prop="intoTotalAmount" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatMoney((scope.row.intoTotalAmount || 0) / 100) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 入库总数量 -->
|
||||
<el-table-column label="入库总数量" align="center" prop="intoTotalNum" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatNumber(scope.row.intoTotalNum) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 入库总金额(元) -->
|
||||
<el-table-column label="入库总金额(元)" align="center" prop="intoTotalAmount" width="130">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatMoney((scope.row.intoTotalAmount || 0) / 100) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 出库数量 -->
|
||||
<el-table-column label="出库数量" align="center" prop="outTotalNum" width="100">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatNumber(scope.row.outTotalNum) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 出库金额(元) -->
|
||||
<el-table-column label="出库金额(元)" align="center" prop="outTotalAmount" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatMoney((scope.row.outTotalAmount || 0) / 100) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 出库总数量 -->
|
||||
<el-table-column label="出库总数量" align="center" prop="outTotalNum" width="120">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatNumber(scope.row.outTotalNum) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 出库总金额(元) -->
|
||||
<el-table-column label="出库总金额(元)" align="center" prop="outTotalAmount" width="130">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ formatMoney((scope.row.outTotalAmount || 0) / 100) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination
|
||||
v-show="total>0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNum"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 导入区域树API
|
||||
import {getTreeArea} from "@/api/canteen/canteenRecord";
|
||||
// 导入库存入库相关API
|
||||
import {
|
||||
listInventoryIntoDetail,
|
||||
exportInventoryIntoDetail,
|
||||
getWarehouseList,
|
||||
getGoodsCategoryDict
|
||||
} from "@/api/report/inventoryhz";
|
||||
|
||||
export default {
|
||||
name: "InventoryIntoDetail",
|
||||
dicts: [],
|
||||
data() {
|
||||
return {
|
||||
// 合计数据
|
||||
summaryData: null,
|
||||
|
||||
// 区域树选项
|
||||
orgOptions: [],
|
||||
selectedOrg: [], // 选中的区域
|
||||
|
||||
// 货品类别相关数据
|
||||
goodsCategoryOptions: [], // 货品类别树形数据
|
||||
selectedCategories: [], // 选中的货品类别路径数组
|
||||
categoryProps: {
|
||||
expandTrigger: 'hover',
|
||||
value: 'id',
|
||||
label: 'dictLabel',
|
||||
children: 'children',
|
||||
emitPath: true,
|
||||
multiple: true
|
||||
},
|
||||
|
||||
// 仓库下拉选项
|
||||
wareHouseOptions: [],
|
||||
|
||||
// 遮罩层
|
||||
loading: true,
|
||||
|
||||
// 显示搜索条件
|
||||
showSearch: true,
|
||||
|
||||
// 总条数
|
||||
total: 0,
|
||||
|
||||
// 表格数据
|
||||
tableListData: [],
|
||||
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
recordId: null, // 单据编号
|
||||
categoryIdList: [], // 货品类别ID列表(包含所有子节点)
|
||||
warehouseIdList: [], // 仓库ID列表
|
||||
goodsName: null, // 货品名称
|
||||
areaIdList: [], // 区域ID列表
|
||||
startDate: null, // 开始日期
|
||||
endDate: null // 结束日期
|
||||
},
|
||||
|
||||
// 日期范围
|
||||
dateRange: this.defaultDateRange(),
|
||||
|
||||
// 日期选择器快捷选项
|
||||
pickerOptions: {
|
||||
shortcuts: [{
|
||||
text: '最近一周',
|
||||
onClick: (picker) => {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 6);
|
||||
picker.$emit('pick', [this.formatDate(start), this.formatDate(end)]);
|
||||
}
|
||||
}, {
|
||||
text: '最近一个月',
|
||||
onClick: (picker) => {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
|
||||
picker.$emit('pick', [this.formatDate(start), this.formatDate(end)]);
|
||||
}
|
||||
}, {
|
||||
text: '最近三个月',
|
||||
onClick: (picker) => {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 3600 * 1000 * 24 * 91);
|
||||
picker.$emit('pick', [this.formatDate(start), this.formatDate(end)]);
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
// 初始化数据
|
||||
this.getTree(); // 获取区域树
|
||||
this.getWareHouseData(); // 获取仓库列表
|
||||
this.getGoodsCategoryData(); // 获取货品类别树
|
||||
this.getList(); // 获取列表数据
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 自定义合计计算方法
|
||||
*/
|
||||
getSummaries(param) {
|
||||
const { columns, data } = param;
|
||||
const sums = [];
|
||||
|
||||
columns.forEach((column, index) => {
|
||||
if (index === 0) {
|
||||
// 第一列显示"合计"
|
||||
sums[index] = '合计';
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据列名判断需要合计的字段
|
||||
const columnProp = column.property;
|
||||
if (this.summaryData) {
|
||||
switch(columnProp) {
|
||||
case 'intoTotalNum':
|
||||
sums[index] = this.formatNumber(this.summaryData.intoTotalNum || 0);
|
||||
break;
|
||||
case 'intoTotalAmount':
|
||||
sums[index] = this.formatMoney((this.summaryData.intoTotalAmount || 0) / 100);
|
||||
break;
|
||||
case 'outTotalNum':
|
||||
sums[index] = this.formatNumber(this.summaryData.outTotalNum || 0);
|
||||
break;
|
||||
case 'outTotalAmount':
|
||||
sums[index] = this.formatMoney((this.summaryData.outTotalAmount || 0) / 100);
|
||||
break;
|
||||
default:
|
||||
// 其他列显示空
|
||||
sums[index] = '';
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sums[index] = '';
|
||||
}
|
||||
});
|
||||
|
||||
return sums;
|
||||
},
|
||||
|
||||
// 保持其他方法不变
|
||||
getGoodsCategoryData() {
|
||||
getGoodsCategoryDict().then((response) => {
|
||||
const data = response.data || response || [];
|
||||
console.log('获取到的货品类别数据:', data);
|
||||
|
||||
// 如果后端返回的是平铺数据,需要转换为树形结构
|
||||
if (data.length > 0 && !data[0].children) {
|
||||
// 使用我们自己的构建树方法
|
||||
this.goodsCategoryOptions = this.buildCategoryTree(data);
|
||||
} else {
|
||||
// 如果已经是树形结构,直接使用
|
||||
this.goodsCategoryOptions = data;
|
||||
}
|
||||
|
||||
console.log('转换后的货品类别树:', this.goodsCategoryOptions);
|
||||
}).catch(error => {
|
||||
console.error('获取货品类别失败:', error);
|
||||
this.goodsCategoryOptions = [];
|
||||
});
|
||||
},
|
||||
|
||||
buildCategoryTree(list) {
|
||||
// 创建根节点(原料和商品)
|
||||
const tree = [];
|
||||
|
||||
// 1. 原料根节点
|
||||
const materialRoot = {
|
||||
id: 25595457052610560,
|
||||
dictLabel: "原料",
|
||||
parentId: -1,
|
||||
children: []
|
||||
};
|
||||
|
||||
// 2. 商品根节点
|
||||
const goodsRoot = {
|
||||
id: 65595542415085568,
|
||||
dictLabel: "商品",
|
||||
parentId: -1,
|
||||
children: []
|
||||
};
|
||||
|
||||
// 将数据按 parent_id 分组
|
||||
const map = {};
|
||||
list.forEach(item => {
|
||||
if (!map[item.id]) {
|
||||
map[item.id] = { ...item, children: [] };
|
||||
}
|
||||
});
|
||||
|
||||
// 构建树结构
|
||||
list.forEach(item => {
|
||||
if (item.parentId === 25595457052610560) {
|
||||
const child = { ...item, children: [] };
|
||||
materialRoot.children.push(child);
|
||||
map[item.id] = child;
|
||||
} else if (item.parentId === 65595542415085568) {
|
||||
const child = { ...item, children: [] };
|
||||
goodsRoot.children.push(child);
|
||||
map[item.id] = child;
|
||||
} else if (item.parentId !== -1 && map[item.parentId]) {
|
||||
const child = { ...item, children: [] };
|
||||
if (!map[item.parentId].children) {
|
||||
map[item.parentId].children = [];
|
||||
}
|
||||
map[item.parentId].children.push(child);
|
||||
map[item.id] = child;
|
||||
}
|
||||
});
|
||||
|
||||
tree.push(materialRoot, goodsRoot);
|
||||
return tree;
|
||||
},
|
||||
|
||||
handleCategoryChange(values) {
|
||||
if (!values || values.length === 0) {
|
||||
this.queryParams.categoryIdList = [];
|
||||
return;
|
||||
}
|
||||
let allCategoryIds = [];
|
||||
values.forEach(path => {
|
||||
const selectedId = path[path.length - 1];
|
||||
const node = this.findCategoryNodeById(selectedId, this.goodsCategoryOptions);
|
||||
if (node) {
|
||||
allCategoryIds.push(...this.getAllChildCategoryIds(node));
|
||||
}
|
||||
});
|
||||
|
||||
this.queryParams.categoryIdList = Array.from(new Set(allCategoryIds));
|
||||
|
||||
console.log("最终传给后台的 categoryIdList =", this.queryParams.categoryIdList);
|
||||
},
|
||||
|
||||
findCategoryNodeById(id, options) {
|
||||
for (const node of options) {
|
||||
if (node.id === id) {
|
||||
return node;
|
||||
}
|
||||
if (node.children && node.children.length > 0) {
|
||||
const found = this.findCategoryNodeById(id, node.children);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
getAllChildCategoryIds(node) {
|
||||
if (!node) return [];
|
||||
|
||||
let ids = [node.id];
|
||||
|
||||
if (node.children && node.children.length > 0) {
|
||||
node.children.forEach(child => {
|
||||
ids = ids.concat(this.getAllChildCategoryIds(child));
|
||||
});
|
||||
}
|
||||
|
||||
return ids;
|
||||
},
|
||||
|
||||
getSelectedOrgIds() {
|
||||
if (!this.selectedOrg || this.selectedOrg.length === 0) return [];
|
||||
const lastValue = this.selectedOrg[this.selectedOrg.length - 1];
|
||||
// 找到对应节点
|
||||
let stack = [...this.orgOptions];
|
||||
let node = null;
|
||||
for (let val of this.selectedOrg) {
|
||||
node = stack.find(item => item.orgId === val);
|
||||
if (!node) break;
|
||||
stack = node.children || [];
|
||||
}
|
||||
|
||||
if (node) {
|
||||
return this.getAllChildIds(node, this.orgOptions);
|
||||
}
|
||||
return [lastValue];
|
||||
},
|
||||
|
||||
getAllChildIds(node, options) {
|
||||
let ids = [node.orgId]; // 当前节点
|
||||
if (node.children && node.children.length > 0) {
|
||||
node.children.forEach(child => {
|
||||
ids = ids.concat(this.getAllChildIds(child, options)); // 递归获取子节点
|
||||
});
|
||||
}
|
||||
return ids;
|
||||
},
|
||||
|
||||
getTree() {
|
||||
getTreeArea().then(res => {
|
||||
this.orgOptions = res || [];
|
||||
});
|
||||
},
|
||||
|
||||
handleAreaChange() {
|
||||
// 区域变化时,重新加载仓库列表
|
||||
this.queryParams.warehouseIdList = [];
|
||||
this.getWareHouseData();
|
||||
},
|
||||
|
||||
handleWarehouseChange() {
|
||||
// 可以在这里添加其他逻辑
|
||||
},
|
||||
|
||||
getWareHouseData() {
|
||||
const areaIdList = this.getSelectedOrgIds();
|
||||
|
||||
console.log("选中的 orgId 列表:", areaIdList, Array.isArray(areaIdList));
|
||||
|
||||
if (!areaIdList || !areaIdList.length) {
|
||||
this.wareHouseOptions = [];
|
||||
return;
|
||||
}
|
||||
getWarehouseList({
|
||||
areaIdList: areaIdList.join(',')
|
||||
}).then(res => {
|
||||
this.wareHouseOptions = res.data || [];
|
||||
});
|
||||
},
|
||||
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
resetQuery() {
|
||||
this.dateRange = this.defaultDateRange();
|
||||
this.selectedOrg = [];
|
||||
this.selectedCategories = [];
|
||||
this.summaryData = null;
|
||||
this.queryParams = {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
recordId: null,
|
||||
categoryIdList: [],
|
||||
warehouseIdList: [],
|
||||
goodsName: null,
|
||||
areaIdList: [],
|
||||
startDate: null,
|
||||
endDate: null
|
||||
};
|
||||
this.resetForm("queryForm");
|
||||
this.getWareHouseData();
|
||||
this.handleQuery();
|
||||
},
|
||||
|
||||
getList() {
|
||||
this.loading = true;
|
||||
|
||||
// 获取选中的区域ID列表
|
||||
this.queryParams.areaIdList = this.getSelectedOrgIds();
|
||||
|
||||
// 处理日期范围
|
||||
if (this.dateRange && this.dateRange.length === 2) {
|
||||
this.queryParams.startDate = this.dateRange[0];
|
||||
this.queryParams.endDate = this.dateRange[1];
|
||||
} else {
|
||||
this.queryParams.startDate = null;
|
||||
this.queryParams.endDate = null;
|
||||
}
|
||||
// 调用API查询
|
||||
listInventoryIntoDetail(this.queryParams).then(response => {
|
||||
const data = response.data || response;
|
||||
this.tableListData = data.rows || [];
|
||||
this.total = Number(data.total) || 0;
|
||||
this.summaryData = data.summary || null;
|
||||
console.log('合计数据:', this.summaryData);
|
||||
this.loading = false;
|
||||
}).catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
|
||||
handleExport() {
|
||||
// 处理日期范围
|
||||
let startDate = '';
|
||||
let endDate = '';
|
||||
|
||||
if (this.dateRange && this.dateRange.length === 2) {
|
||||
const start = this.dateRange[0];
|
||||
const end = this.dateRange[1];
|
||||
|
||||
startDate = start + ' 00:00:00';
|
||||
endDate = end + ' 23:59:59';
|
||||
}
|
||||
|
||||
// 构建参数
|
||||
let param = {
|
||||
pageNum: this.queryParams.pageNum,
|
||||
pageSize: this.queryParams.pageSize,
|
||||
recordId: this.queryParams.recordId,
|
||||
categoryIdList: this.queryParams.categoryIdList,
|
||||
warehouseIdList: this.queryParams.warehouseIdList,
|
||||
materialName: this.queryParams.materialName,
|
||||
areaIdList: this.getSelectedOrgIds(),
|
||||
startDate: startDate,
|
||||
endDate: endDate
|
||||
};
|
||||
|
||||
// 使用download方法(参考另一个模块)
|
||||
this.$modal.confirm('是否确认导出货品汇总明细数据项?').then(() => {
|
||||
this.loading = true;
|
||||
|
||||
// 使用download方法
|
||||
this.download(
|
||||
'/smart-canteen/drp/inventoryIntohz/goods/summary/export',
|
||||
param,
|
||||
`货品库存明细_${new Date().getTime()}.xlsx`
|
||||
).then(() => {
|
||||
this.loading = false;
|
||||
this.$modal.msgSuccess("导出成功");
|
||||
}).catch(error => {
|
||||
this.loading = false;
|
||||
console.error('导出失败:', error);
|
||||
this.$modal.msgError("导出失败");
|
||||
});
|
||||
}).catch(() => {
|
||||
// 用户取消
|
||||
});
|
||||
},
|
||||
|
||||
handlePrint() {
|
||||
const printData = {
|
||||
title: '库存入库明细表',
|
||||
columns: [
|
||||
{ prop: 'categoryName', label: '货品类别', width: 120 },
|
||||
{ prop: 'areaName', label: '所属区域', width: 120 },
|
||||
{ prop: 'warehouseName', label: '所属仓库', width: 120 },
|
||||
{ prop: 'intoTotalNum', label: '入库数量', width: 100 },
|
||||
{ prop: 'intoTotalAmount', label: '入库金额(元)', width: 120 },
|
||||
{ prop: 'intoTotalNum', label: '入库总数量', width: 120 },
|
||||
{ prop: 'intoTotalAmount', label: '入库总金额(元)', width: 130 },
|
||||
{ prop: 'outTotalNum', label: '出库数量', width: 100 },
|
||||
{ prop: 'outTotalAmount', label: '出库金额(元)', width: 120 },
|
||||
{ prop: 'outTotalNum', label: '出库总数量', width: 120 },
|
||||
{ prop: 'outTotalAmount', label: '出库总金额(元)', width: 130 }
|
||||
],
|
||||
data: this.tableListData,
|
||||
queryParams: this.queryParams
|
||||
};
|
||||
|
||||
const printWindow = window.open('', '_blank');
|
||||
const printContent = this.generatePrintHTML(printData);
|
||||
printWindow.document.write(printContent);
|
||||
printWindow.document.close();
|
||||
printWindow.focus();
|
||||
setTimeout(() => {
|
||||
printWindow.print();
|
||||
printWindow.close();
|
||||
}, 500);
|
||||
},
|
||||
|
||||
generatePrintHTML(printData) {
|
||||
let html = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>${printData.title}</title>
|
||||
<style>
|
||||
body { font-family: "Microsoft YaHei", Arial, sans-serif; margin: 20px; }
|
||||
h2 { text-align: center; margin-bottom: 20px; }
|
||||
table { width: 100%; border-collapse: collapse; font-size: 12px; }
|
||||
th, td { border: 1px solid #000; padding: 8px; text-align: center; }
|
||||
th { background-color: #f0f0f0; font-weight: bold; }
|
||||
.print-info { margin-bottom: 20px; font-size: 12px; }
|
||||
@media print {
|
||||
@page { size: landscape; margin: 10mm; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>${printData.title}</h2>
|
||||
<div class="print-info">
|
||||
<p>打印时间:${new Date().toLocaleString()}</p>
|
||||
<p>共 ${printData.data.length} 条记录</p>
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
`;
|
||||
|
||||
printData.columns.forEach(col => {
|
||||
html += `<th>${col.label}</th>`;
|
||||
});
|
||||
|
||||
html += `
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
`;
|
||||
|
||||
printData.data.forEach(row => {
|
||||
html += '<tr>';
|
||||
printData.columns.forEach(col => {
|
||||
let value = row[col.prop] || '-';
|
||||
if (col.prop === 'intoTotalAmount' || col.prop === 'outTotalAmount') {
|
||||
value = this.formatMoney((value || 0) / 100);
|
||||
} else if (col.prop === 'intoTotalNum' || col.prop === 'outTotalNum') {
|
||||
value = this.formatNumber(value);
|
||||
}
|
||||
html += `<td>${value}</td>`;
|
||||
});
|
||||
html += '</tr>';
|
||||
});
|
||||
|
||||
html += `
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
return html;
|
||||
},
|
||||
|
||||
defaultDateRange() {
|
||||
const end = new Date();
|
||||
const start = new Date();
|
||||
start.setTime(start.getTime() - 30 * 24 * 60 * 60 * 1000);
|
||||
return [this.formatDate(start), this.formatDate(end)];
|
||||
},
|
||||
|
||||
formatDate(date) {
|
||||
if (!date) return '';
|
||||
const d = new Date(date);
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
},
|
||||
|
||||
formatDateTime(date) {
|
||||
if (!date) return '';
|
||||
const d = new Date(date);
|
||||
const year = d.getFullYear();
|
||||
const month = String(d.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(d.getDate()).padStart(2, '0');
|
||||
const hours = String(d.getHours()).padStart(2, '0');
|
||||
const minutes = String(d.getMinutes()).padStart(2, '0');
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
},
|
||||
|
||||
formatMoney(value) {
|
||||
if (value === null || value === undefined || value === '') return '0.00';
|
||||
return Number(value).toFixed(2);
|
||||
},
|
||||
|
||||
formatNumber(value) {
|
||||
if (value === null || value === undefined || value === '') return '0';
|
||||
return Number(value);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* 合计行样式增强 */
|
||||
::v-deep .el-table__footer-wrapper tbody td {
|
||||
background-color: #f5f7fa;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
::v-deep .el-table__footer-wrapper tbody td:first-child {
|
||||
font-weight: bold;
|
||||
color: #409EFF;
|
||||
}
|
||||
|
||||
/* 表格样式 */
|
||||
::v-deep .el-table__fixed-right td.blue-record-col .cell {
|
||||
color: #1677ff !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 调整表单样式 */
|
||||
::v-deep .el-form-item {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
/* 调整按钮样式 */
|
||||
::v-deep .el-button {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
::v-deep .el-form-item__content {
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
/* 调整表格样式 */
|
||||
::v-deep .el-table {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
::v-deep .el-table th {
|
||||
background-color: #f5f7fa;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
::v-deep .el-pagination {
|
||||
margin-top: 15px;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue