材料管理开发

dev_xd
lj7788@126.com 2025-07-17 18:40:58 +08:00
parent 3347dd0be5
commit 48daa70fcd
12 changed files with 729 additions and 20 deletions

View File

@ -157,7 +157,7 @@ const materGetConcreteMaterialActQuantityGhInfoService=data=>{
})
}
//材料销号制-时间段内工号申领情况
//材料销号制-获取材料销号制混凝土楼号维度信息
const materGetConcreteMaterialActQuantityBuildingNoInfoService=data=>{
return request({
url: '/manage/bgscreen/machMater/materGetConcreteMaterialActQuantityBuildingNoInfoService',
@ -166,6 +166,15 @@ const materGetConcreteMaterialActQuantityBuildingNoInfoService=data=>{
})
}
//材料销号制-获取材料销号制混凝土楼层维度信息
const materGetConcreteMaterialActQuantityFloorLevelInfoService=data=>{
return request({
url: '/manage/bgscreen/machMater/materGetConcreteMaterialActQuantityFloorLevelInfoService',
method: 'get',
params: data
})
}
//材料销号制-获取用量情况统计服务
const materGetProjectChaoHaoStatisticsRPTService=data=>{
return request({
@ -217,6 +226,7 @@ export default{
machSelectMachineCardImageList,
machGetCertInfoList,
materGetConcreteMaterialActQuantityBuildingNoInfoService,
materGetConcreteMaterialActQuantityFloorLevelInfoService,
materGetConcreteMaterialActQuantityGhInfoService,
materGetProjectChaoHaoStatisticsRPTService,
materGetReportConcreteExceedReasonService,

View File

@ -0,0 +1,229 @@
<template>
<div :style="{ 'height': height + 'px' }" ref="chart"> </div>
</template>
<script>
export default {
props: {
dataList: {
type: Object,
},
yaxis: {
type: Boolean
},
height: {
type: Number
}
},
data() {
return {
option: {},
}
},
mounted() {
this.init()
},
methods: {
init() {
this.getChartData()
},
//
getChartData() {
var chChartBar = echarts.init(this.$refs.chart);
this.$nextTick(() => {
this.echartBar(chChartBar, this.dataList, this.yaxis)
})
},
echartBar(myChart, objs, state) {
let newPromise = new Promise((resolve) => {
resolve()
})
//echarts
newPromise.then(() => {
var unit = ''
if (objs.unit) {
unit = '单位:' + objs.unit
}
var yAxis = []
var grid = ''
if (state == true) {
yAxis.push(
{
name: unit,
nameTextStyle: { //Y
color: '#42d0ff',
fontSize: 14,
},
max: objs.max,
type: "value",
axisLabel: {
textStyle: {
color: "#cbdaff",
},
formatter: "{value}",
},
splitLine: {
lineStyle: {
type: "dashed",
color: "#2f4472",
},
},
axisLine: {
show: true,
lineStyle: {
color: "#2f4472",
},
},
}
)
grid = {
left: "20%",
top: "20%",
right: "0%",
bottom: "10%",
}
} else {
yAxis.push(
{
nameTextStyle: { //Y
color: '#42d0ff',
fontSize: 14,
},
max: objs.max,
type: "value",
axisLabel: { show: false },
axisTick: { show: false },
splitLine: {
lineStyle: {
type: "dashed",
color: "#2f4472",
},
},
axisLine: {
show: true,
lineStyle: {
color: "#2f4472",
},
},
}
)
grid = {
left: "0%",
top: "20%",
right: "0%",
bottom: "10%",
}
}
this.option = {
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
label: {
show: true,
},
},
},
grid: grid,
xAxis: {
data: objs.xData,
axisLine: {
show: true, //X线
lineStyle: {
color: "#2f4472",
width: 1,
},
},
axisTick: {
show: true, //X
alignWithLabel: true,
},
axisLabel: {
show: true,
textStyle: {
color: "#cbdaff", //X
fontSize: 14,
},
interval: 0,
},
},
yAxis: yAxis,
series: [
{
name: objs.legend[0],
type: "bar",
barWidth: 10,
barGap: 2,
label: {
normal: {
show: true,
position: "top",
color: "#fff"
},
},
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(64,124,254,1)",
},
{
offset: 1,
color: "rgba(64,124,254,0.2)",
},
]),
},
},
data: objs.yData_1,
},
{
name: objs.legend[1],
type: "bar",
barWidth: 10,
barGap: 2,
label: {
normal: {
show: true,
position: "inside",
color: "#fff"
},
},
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: "rgba(25,210,204,1)",
},
{
offset: 1,
color: "rgba(25,210,204,0.2)",
},
]),
},
},
data: objs.yData_2,
},
],
};
myChart.setOption(this.option);
window.onresize = myChart.resize;
})
},
},
watch: {
data: function () {
this.init()
}
}
}
</script>

View File

@ -0,0 +1,105 @@
<template>
<div class="many-chart-max" ref="process" @mouseover="MouseEnter" @mouseout="MouseLeave" :key="chartWidht">
<div class="many-chart-min" :style="{ 'width': (dataList.length * chartWidht) + 'px' }">
<div v-for="(item, i) in forData" :key="i" :style="{ 'width': chartWidht + 'px' }">
<material-many-bar-chart :yaxis="i == 0 ? true : false" :height="200"
:dataList="item"></material-many-bar-chart>
<div class="many-chart-text" style="text-align: center ">{{ item.text }}</div>
</div>
</div>
</div>
</template>
<script>
import manyBarChart from './manyBarChart.vue'
export default {
components: {
'material-many-bar-chart': manyBarChart
},
props: {
dataList: {
type: Array,
default: () => []
}
},
data() {
return {
forData: [],
index: 0,
interval: '',
chartWidht: 0,
chartHeight: 0,
count: 4,
}
},
created() {
this.init()
},
mounted() {
setTimeout(() => {
let is1K = this.$dpi() == "1K";
let is2K = this.$dpi() == "2K";
this.count = is1K ? 4 : is2K ? 6 : 8;
let width = this.$el.clientWidth
this.chartWidht = width / this.count;
}, 800);
},
methods: {
init() {
this.index = 0
var tmps = this.dataList
tmps.map(x => {
x.merge = x.yData_1.concat(x.yData_2)
return
})
let max = 0
for (let i = 0; i < tmps.length; i++) {
for (let j = 0; j < tmps[i].merge.length; j++) {
if (max < Number(tmps[i].merge[j])) {
max = Number(tmps[i].merge[j])
}
}
}
tmps.map(x => {
x.max = max
return
})
this.forData = tmps
this.interval = setInterval(this.scroll, 5000);
},
scroll() {
let offsetWidth = this.chartWidht;
if (this.index == this.forData.length - this.count) {
this.index = 0
} else {
this.index += 1
}
$(this.$refs.process).animate({ scrollLeft: (offsetWidth * this.index) + 'px' })
},
MouseEnter() {//
clearInterval(this.interval);
},
MouseLeave() {//
this.interval = setInterval(this.scroll, 5000);
},
},
watch: {
dataList: function () {
clearInterval(this.interval);
this.init()
}
}
}
</script>
<style lang="less">
.many-chart-max {
.many-chart-text {
font-size: 18px;
position: relative;
top: -10px;
}
}
</style>

View File

@ -0,0 +1,82 @@
<template>
<div class="header-btn-max" @mouseleave="mouseleaveBtn">
<div :class="nav != ''?'more-btn active':'more-btn'" @mouseenter="mouseenterBtn">
{{text}}
<i class="el-icon-caret-bottom"></i>
</div>
<div class="header-btn-list" v-show="show" style="display: none">
<div class="header-btn-list-arrow"></div>
<div class="header-btn-list-item" :style="{width:widths+'px'}">
<div class="header-btn-list-padding">
<button type="button" style="width: 130px" :class="btnNav==i||text==item.text?'active':''" v-for="(item,i) in list"
@click="buttonClick(i,item)" :key="i">{{item.ghName}}</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
label: {
type: String
},
nav: {
type: String
},
list: {
type: Array,
default: () => []
},
},
data() {
return {
show: false,
widths: 0,
btnNav: -1,
chooseMenu: {},
text:'',
}
},
mounted() {
this.text = this.label
this.init()
},
methods: {
init() {
this.width()
},
width() {
if (this.list) {
if (this.list.length > 4) {
this.widths = 4 * 150 + 16
} else {
this.widths = this.list.length * 150 + 16
}
}
},
buttonClick(i, item) {
this.btnNav = i
this.text = item.text
this.$emit('value',item);
},
mouseenterBtn() {
this.show = true
},
mouseleaveBtn() {
this.show = false
}
},
watch: {
nav:function (n,o) {
if(n == ''){
this.btnNav = -1
}
},
list:function (n) {
this.width()
}
},
}
</script>

View File

@ -175,13 +175,13 @@
<script>
import debounce from "lodash.debounce";
import processControlBar from "./processControlBar.vue";
import machineInfoDialog from "./machineInfoDialog.vue";
import baiduMap from "./baiduMap.vue";
import processControlBar from "./components/processControlBar.vue";
import machineInfoDialog from "./components/machineInfoDialog.vue";
import baiduMap from "./components/baiduMap.vue";
import MyChart from "@/components/MyChart.vue";
import SvgIcon from "@/components/SvgIcon.vue";
import staffSurveyChart from "@/components/staffSurveyChart.vue";
import certInfoDataDialog from "./certInfoDataDialog.vue";
import certInfoDataDialog from "./components/certInfoDataDialog.vue";
export default {
components: {
processControlBar,

View File

@ -4,12 +4,41 @@
<module-one-2-3 label="近期工单" class="h66 order-data-module">
<div class="element-table-ranking" :key="orderDataKey">
<el-table :data="todaysWorkOrderData.data" class="scroll mytable" :height="orderDataHeight">
<el-table-column v-for="(st, idx) in todaysWorkOrderData.labels" :prop="st.data" :key="idx" :width="st.width" :label="st.label" show-overflow-tooltip></el-table-column>
<el-table-column v-for="(st, idx) in todaysWorkOrderData.labels" :prop="st.data" :key="idx"
:width="st.width" :label="st.label" show-overflow-tooltip></el-table-column>
</el-table>
</div>
</module-one-2-3>
<module-one-1-3 label="混凝土使用情况" class="h33"> </module-one-1-3>
<module-one-1-3 label="混凝土使用情况" class="h33 concrete-module" :key="workerOrderKey" v-loading="workerOrderLoading">
<div class="xhz-concrete-nav">
<div class="sjk-chart-line-title-tz" style="padding: 10px 20px 0">
<button :class="schemeNav == 0 ? 'active' : ''" @click="onSchemeBtnA(0, {})">全部</button>
<button :class="schemeNav == index + 1 ? 'active' : ''" @click="onSchemeBtnA(index + 1, item)"
v-for="(item, index) in workerOrder" :key="index">{{ item.ghName }}</button>
<more-button :nav="moreNav" :label="moreLabel" v-if="workerOrerMore.length > 0" :list="workerOrerMore"
@value="onMoreBtn"></more-button>
</div>
<div style="display: flex">
<div class="xhz-concrete-legend xhz-concrete-legend-1"><button></button> 设计量</div>
<div class="xhz-concrete-legend xhz-concrete-legend-2"><button></button> 消耗量</div>
</div>
<div class="sjk-chart-line-title" style="padding: 10px 0 0">
<div :class="trendBtnNav == 1 ? 'active' : ''" @click="onClickTemperatureTrend(1)"></div>
<div :class="trendBtnNav == 2 ? 'active' : ''" @click="onClickTemperatureTrend(2)"></div>
</div>
</div>
<div style="display: flex;padding: 0 10px;" class="xhz-concrete-chart"
:class="{ 'no-data': moreData.length == 0 }">
<many-chart :dataList="moreData" v-if="moreData.length > 0"></many-chart>
<div class="no-data" v-else>
<img src="images/nodata.png" class="no-data-img" />
<div style="text-align: center;" class="no-data-text">暂无数据</div>
</div>
</div>
</module-one-1-3>
</el-col>
<el-col :span="6" class="h100">
@ -20,7 +49,13 @@
<script>
import debounce from "lodash.debounce";
import moreButton from "./components/moreButton.vue";
import manyChart from "./components/manyChart.vue";
export default {
components: {
moreButton,
manyChart,
},
data() {
return {
dpi: "",
@ -33,6 +68,16 @@ export default {
orderDataHeight: 500,
orderInterval: null,
orderDataKey: 0,
//使
workerOrder: [],
workerOrerMore: [],
schemeNav: 0,
moreNav: '',
trendBtnNav: 1,
moreLabel: '更多',
moreData: [],
workerOrderKey: 0,
workerOrderLoading: false,
};
},
mounted() {
@ -60,11 +105,11 @@ export default {
resize() {
let is1K = this.$dpi() == "1K";
let is2K = this.$dpi() == "2K";
console.log("---->", is1K, is2K);
this.orderDataHeight = is1K ? 580 : is2K ? 810 : 1275;
this.getOrderDataLabel();
this.chartKey++;
this.orderDataKey++;
this.workerOrderKey++;
},
init() {
if (!this.selProject) {
@ -74,14 +119,171 @@ export default {
//
this.loadTodaysWorkOrderData();
// let data = {
// projectId: this.selProject.id,
// startTime: this.$dt("2025-01-01").format("YYYY-MM-DD HH:mm:ss"),
// endTime: this.$dt(new Date()).format("YYYY-MM-DD HH:mm:ss"),
// };
// this.$api.machMater.materGetConcreteMaterialActQuantityBuildingNoInfoService(data).then((d) => {
// console.log("====>", d);
// });
//
this.loadWorkOrderData();
},
//
async getConcreteMaterialActQuantityBuildingNoInfoService(type) {
let postData = {
projectId: this.selProject.id,
}
this.moreData = []
if (type == 1) {
postData.startTime = this.$dt(this.getlastMonth()).format("YYYY-MM-DD 00:00:00");
postData.endTime = this.$dt(new Date()).format("YYYY-MM-DD 23:59:59");
}
this.workerOrderLoading = true
let result = await this.$api.machMater.materGetConcreteMaterialActQuantityBuildingNoInfoService(postData)
result = result.data;
if (result && result.code == '000000' && result.data) {
let moreDataTemp = []
result.data.forEach(item => {
if (moreDataTemp.length <= 0) {
moreDataTemp.push({
text: item.oneName,
legend: ["设计量", "消耗量"],
unit: 'm³',
xData: [],
yData_1: [],
yData_2: []
})
}
if (JSON.stringify(moreDataTemp).indexOf(item.oneName) < 0) {
moreDataTemp.push({
text: item.oneName,
legend: ["设计量", "消耗量"],
unit: 'm³',
xData: [],
yData_1: [],
yData_2: []
})
}
})
moreDataTemp.forEach(item => {
result.data.forEach(item1 => {
if (item.text == item1.oneName) {
item.xData.push(item1.materielModel)
item.yData_1.push(item1.yhl.toFixed(1))
item.yData_2.push(item1.actQuantity.toFixed(1))
}
})
})
moreDataTemp.forEach(item => {
this.moreData.push({
text: item.text,
legend: item.legend,
unit: item.unit,
xData: item.xData,
yData_1: item.yData_1,
yData_2: item.yData_2,
})
})
} else {
this.moreData = []
}
this.workerOrderLoading = false
this.workerOrderKey++;
},
//
async getConcreteMaterialActQuantityFloorLevelInfoService(type, ghId) {
this.moreData = []
let postData = {
projectId: this.selProject.id,
}
this.moreData = []
if (type == 1) {
postData.startTime = this.$dt(this.getlastMonth()).format("YYYY-MM-DD 00:00:00");
postData.endTime = this.$dt(new Date()).format("YYYY-MM-DD 23:59:59");
}
this.workerOrderLoading = true
let result = await this.$api.machMater.materGetConcreteMaterialActQuantityFloorLevelInfoService(postData);
result = result.data;
if (result && result.code == '000000' && result.data) {
let moreDataTemp = []
result.data.forEach(item => {
if (moreDataTemp.length <= 0) {
moreDataTemp.push({
text: item.threeName,
legend: ["设计量", "消耗量"],
unit: 'm³',
time: item.add_time,
xData: [],
yData_1: [],
yData_2: []
})
}
if (JSON.stringify(moreDataTemp).indexOf(item.threeName) < 0) {
moreDataTemp.push({
text: item.threeName,
legend: ["设计量", "消耗量"],
unit: 'm³',
time: item.add_time,
xData: [],
yData_1: [],
yData_2: []
})
}
})
moreDataTemp.forEach(item => {
result.data.forEach(item1 => {
if (item.text == item1.threeName) {
item.xData.push(item1.materielModel)
item.yData_1.push(item1.yhl.toFixed(1))
item.yData_2.push(item1.actQuantity.toFixed(1))
}
})
})
this.moreData = moreDataTemp.sort((prev, next) => prev.time - next.time)
this.workerOrderLoading = false
this.workerOrderKey++;
}
},
async onClickTemperatureTrend(n) {
this.trendBtnNav = n
if (this.schemeNav == 0) {
await this.getConcreteMaterialActQuantityBuildingNoInfoService(n)
} else {
await this.getConcreteMaterialActQuantityFloorLevelInfoService(n, this.ghId)
}
},
async onSchemeBtnA(n, item) {
this.schemeNav = n
if (n == 0) {
await this.getConcreteMaterialActQuantityBuildingNoInfoService(this.trendBtnNav)
} else {
this.ghId = item.ghId
await this.getConcreteMaterialActQuantityFloorLevelInfoService(this.trendBtnNav, item.ghId)
}
this.moreNav = ''
},
async onMoreBtn(item) {
this.ghId = item.id
this.schemeNav = -1
this.moreNav = item.text
await this.getConcreteMaterialActQuantityFloorLevelInfoService(this.trendBtnNav, item.id)
},
loadWorkOrderData() {
let data = {
projectId: this.selProject.id
};
this.$api.machMater.materGetConcreteMaterialActQuantityGhInfoService(data).then(d => {
let tmps = (d.data?.data || []).map(item => {
item.text = item.ghName
item.id = item.ghId
return item;
});
this.workerOrder = tmps.slice(0, 3);
this.workerOrerMore = tmps;
this.onSchemeBtnA(0, {});
});
},
loadTodaysWorkOrderData() {
let data = {
@ -120,7 +322,7 @@ export default {
getOrderDataLabel() {
let is1K = this.$dpi() == "1K";
let is2K = this.$dpi() == "2K";
let newFormatData=this.todaysWorkOrderData.data;
let newFormatData = this.todaysWorkOrderData.data;
this.todaysWorkOrderData.labels = [
{
label: "序号",
@ -284,6 +486,21 @@ export default {
}
}
},
getlastMonth() {
let now = new Date();
//
let nowDate = now.getDate();
let lastMonth = new Date(now.getTime());
// 1
lastMonth.setMonth(lastMonth.getMonth());
// 0
lastMonth.setDate(0);
//
let daysOflastMonth = lastMonth.getDate();
//
lastMonth.setDate(nowDate > daysOflastMonth ? daysOflastMonth : nowDate);
return lastMonth;
}
},
};
</script>
@ -294,9 +511,11 @@ export default {
&.h66 {
height: calc(66% - 20px);
}
&.h100 {
height: calc(100% - 20px);
}
&.h33 {
height: calc(33% - 20px);
}
@ -306,16 +525,55 @@ export default {
.module-ctx {
padding: 0px 1px 0px 0px;
}
.element-table-ranking {
padding: 0px;
}
}
.concrete-module {
.xhz-concrete-nav {
margin-top: -12px;
.sjk-chart-line-title-tz {
button {
width: auto;
border: 0;
padding: 5px 10px;
}
}
}
.xhz-concrete-chart {
&.no-data {
height: 100%;
justify-content: center;
align-items: center;
}
.no-data {
width: 100%;
text-align: center;
.no-data-img {
width: 120px;
}
.no-data-text {
font-size: 14px;
}
}
}
}
@media (max-width: 1920px) {
.order-data-module {
.element-table-ranking {
.el-table {
th {
padding: 0px;
.cell {
padding-left: 0px;
padding-right: 0px;

View File

@ -270,7 +270,7 @@ public class MachMaterController extends BaseController {
/**
* -
* -
*/
@GetMapping("/materGetConcreteMaterialActQuantityBuildingNoInfoService")
public AjaxResult materGetConcreteMaterialActQuantityBuildingNoInfoService(Long projectId, String startTime, String endTime) throws Exception {
@ -292,6 +292,31 @@ public class MachMaterController extends BaseController {
}
/**
* -
*/
@GetMapping("/materGetConcreteMaterialActQuantityFloorLevelInfoService")
public AjaxResult materGetConcreteMaterialActQuantityFloorLevelInfoService(Long projectId, String startTime, String endTime,String ghId) throws Exception {
Map<String, Object> map = getConfig(projectId, "mater");
String url = map.get("url").toString();
url += "/MklBaseController/getService";
JSONObject paramJson = (JSONObject) map.get("obj");
if (StringUtils.isNotEmpty(startTime)) {
paramJson.put("startTime", startTime);
}
if (StringUtils.isNotEmpty(endTime)) {
paramJson.put("endTime", endTime);
}
if(StringUtils.isNotEmpty(ghId)){
paramJson.put("ghId", ghId);
}
paramJson.put("service", "getConcreteMaterialActQuantityFloorLevelInfoService");
HttpUtils httpUtils = new HttpUtils();
String result = httpUtils.sendGet(url, HttpUtils.jsonToGetParams(paramJson));
return AjaxResult.success(JSONObject.parseObject(result));
}
/**
* -
*/