feat: 监理月报功能新增以及BUG修改

This commit is contained in:
kun 2023-09-05 18:42:17 +08:00
parent d13c07e168
commit 24278cc3d9
20 changed files with 881 additions and 86 deletions

View File

@ -2,9 +2,9 @@
NODE_ENV = 'development'
# 本地环境接口地址(/api/index.ts文件中使用)
# VITE_API_URL = 'http://192.168.34.155:6688'
VITE_API_URL = 'http://192.168.34.155:6688'
VITE_WPAPI_URL = "http://182.90.224.147:8081"
VITE_API_URL = "http://182.90.224.147:6688"
# VITE_API_URL = "http://182.90.224.147:6688"
# 上传
# VITE_ULD_API_URL = 'http://192.168.34.155:8012/onlinePreview?url='

View File

@ -3,7 +3,7 @@ NODE_ENV = "production"
# 线上环境接口地址(easymock)
# VITE_API_URL = "http://139.9.66.234:6688"
VITE_API_URL = "http://182.90.224.147:6688"
VITE_API_URL = "http://182.90.224.147:6677"
# VITE_API_URL = "http://182.90.224.147:9012"
VITE_WPAPI_URL = "http://182.90.224.147:8081"
# VITE_API_URL = "http://101.43.164.214:6688"

View File

@ -660,3 +660,9 @@ export const hoistEquipInstallApplyFile = (params: any) => {
export const hoistEquipApplyUse = (params: any) => {
return http.post(BASEURL + `/ent/liftingDevice/useApply`, params);
};
// 监理月报
// 提交月报
export const submitMonthlyReport = (params: any) => {
return http.post(BASEURL + `/ent/monthlyReport/add`, params);
};

View File

@ -685,3 +685,9 @@ export const hoistEquipApplyFile = (params: any) => {
export const hoistEquipInstallApplyFile = (params: any) => {
return http.post(BASEURL + `/project/liftingDeviceUse/queryAnnexFile`, params);
};
// 监理月报
// 提交月报
export const submitMonthlyReport = (params: any) => {
return http.post(BASEURL + `/project/monthlyReport/add`, params);
};

View File

@ -60,7 +60,7 @@
<el-table
:data="recordData"
class="el-table"
max-height="300"
height="200"
:row-style="{ height: '40px' }"
:header-cell-style="{ backgroundColor: '#F5F7FA', textAlign: 'center', height: '40px' }"
:cell-style="{ textAlign: 'center', height: '40px' }"
@ -369,14 +369,24 @@ const onUpload = async (row: any, index: any) => {
if (row.fileList.length > 0) {
let arr: any = [];
row.fileList.map(item => {
if (item.response) {
arr.push({
response: { ...item.response, url: item.response.fileUrl },
name: item.response.fileName,
url: item.response.fileUrl,
size: +item.response.fileSize,
type: item.response.contentType
});
} else {
arr.push({
response: { ...item, url: item.fileUrl },
name: item.fileName,
url: item.fileUrl,
size: +item.fileSize,
type: item.contentType
});
}
delete item.response;
arr.push({
response: { ...item, url: item.fileUrl },
name: item.fileName,
url: item.fileUrl,
size: +item.fileSize,
type: item.contentType
});
});
current.value.files = arr;
console.log(current.value.files);

View File

@ -493,6 +493,7 @@ onMounted(() => {});
box-shadow: 0px 4px 8px 0px rgba(48, 62, 100, 0.2);
border-radius: 8px 8px 8px 8px;
padding: 15px 20px;
overflow: hidden;
.content-title {
@include title;
margin-top: 45px;

View File

@ -488,6 +488,7 @@ onMounted(() => {});
box-shadow: 0px 4px 8px 0px rgba(48, 62, 100, 0.2);
border-radius: 8px 8px 8px 8px;
padding: 15px 20px;
overflow: hidden;
.content-title {
@include title;
margin-top: 45px;

View File

@ -489,6 +489,7 @@ onMounted(() => {});
box-shadow: 0px 4px 8px 0px rgba(48, 62, 100, 0.2);
border-radius: 8px 8px 8px 8px;
padding: 15px 20px;
overflow: hidden;
.content-title {
@include title;
margin-top: 45px;

View File

@ -41,7 +41,7 @@
<el-table
:data="recordData"
class="el-table"
max-height="300"
height="200"
:row-style="{ height: '40px' }"
:header-cell-style="{ backgroundColor: '#F5F7FA', textAlign: 'center', height: '40px' }"
:cell-style="{ textAlign: 'center', height: '40px' }"

View File

@ -1026,6 +1026,7 @@ onMounted(() => {
box-shadow: 0px 4px 8px 0px rgba(48, 62, 100, 0.2);
border-radius: 8px 8px 8px 8px;
padding: 15px 20px;
overflow: hidden;
.content-title {
@include title;
margin-top: 45px;

View File

@ -459,6 +459,7 @@ onMounted(() => {});
box-shadow: 0px 4px 8px 0px rgba(48, 62, 100, 0.2);
border-radius: 8px 8px 8px 8px;
padding: 15px 20px;
overflow: hidden;
.content-title {
@include title;
margin-top: 45px;

View File

@ -1010,6 +1010,7 @@ onMounted(() => {
box-shadow: 0px 4px 8px 0px rgba(48, 62, 100, 0.2);
border-radius: 8px 8px 8px 8px;
padding: 15px 20px;
overflow: hidden;
.content-title {
@include title;
margin-top: 45px;

View File

@ -467,6 +467,7 @@ onMounted(() => {});
box-shadow: 0px 4px 8px 0px rgba(48, 62, 100, 0.2);
border-radius: 8px 8px 8px 8px;
padding: 15px 20px;
overflow: hidden;
.content-title {
@include title;
margin-top: 45px;

View File

@ -60,7 +60,7 @@
<el-table
:data="recordData"
class="el-table"
max-height="300"
height="200"
:row-style="{ height: '40px' }"
:header-cell-style="{ backgroundColor: '#F5F7FA', textAlign: 'center', height: '40px' }"
:cell-style="{ textAlign: 'center', height: '40px' }"
@ -369,14 +369,24 @@ const onUpload = async (row: any, index: any) => {
if (row.fileList.length > 0) {
let arr: any = [];
row.fileList.map(item => {
if (item.response) {
arr.push({
response: { ...item.response, url: item.response.fileUrl },
name: item.response.fileName,
url: item.response.fileUrl,
size: +item.response.fileSize,
type: item.response.contentType
});
} else {
arr.push({
response: { ...item, url: item.fileUrl },
name: item.fileName,
url: item.fileUrl,
size: +item.fileSize,
type: item.contentType
});
}
delete item.response;
arr.push({
response: { ...item, url: item.fileUrl },
name: item.fileName,
url: item.fileUrl,
size: +item.fileSize,
type: item.contentType
});
});
current.value.files = arr;
console.log(current.value.files);

View File

@ -488,6 +488,7 @@ onMounted(() => {});
box-shadow: 0px 4px 8px 0px rgba(48, 62, 100, 0.2);
border-radius: 8px 8px 8px 8px;
padding: 15px 20px;
overflow: hidden;
.content-title {
@include title;
margin-top: 45px;

View File

@ -0,0 +1,699 @@
<template>
<div class="overview">
<el-dialog :show-close="false" v-model="visible1" width="1305px" @close="closeMain">
<template #title>
<div class="title-detail">
<span>新增月报</span>
<el-icon>
<close @click="closeMain" />
</el-icon>
</div>
</template>
<div class="report-content" id="monthlyReport">
<div class="title">天地一号御花园工程项目</div>
<div class="title">建设监理工作月报</div>
<div class="sub-title">
<span></span>
<el-input v-model.number="formData.stage" style="width: 60px; margin: 0 5px" @blur="e => validatorNumber(e, 'stage')" />
<span></span>
</div>
<div class="sub-title">天眼监理工程有限公司项目监理部</div>
<div class="title">监理月报签认表</div>
<div class="engineer-name">工程名称天地一号御花园项目</div>
<div class="report-content-part1">
<div> 监理工程师</div>
<div>
按照建设工程监理规范和公司的有关规定 完成了天地一号御花园工程 月份监理月报
编写工作请予以审查签认
</div>
<div>编制人员</div>
<div>土建专业监理工程师</div>
<div>水暖专业监理工程师</div>
<div>电气专业监理工程师</div>
<div>签字</div>
</div>
<div class="report-content-part2">
<div>项目监理部总监理工程师签认意见</div>
<div>
<el-input v-model="formData.signOpinion" :rows="3" type="textarea" />
</div>
<div>
<span>总监理工程师</span>
<span></span>
<span></span>
</div>
</div>
<div class="report-content-part3">
<div>
<div>工程名称</div>
<div>天地一号御花园项目</div>
<div>设计单位</div>
<div>威海城市规划建筑设计院</div>
</div>
<div>
<div>建设单位</div>
<div>中国建筑第八分公司</div>
<div>施工单位</div>
<div>秦天建设劳务施工有限公司</div>
</div>
</div>
<div class="report-content-part4">
<div><span>形象进度完成情况</span></div>
<div>
<div>
<div><span>实际完成</span></div>
<div>
<el-input
v-model="formData.actualCompletion"
:rows="3"
type="textarea"
placeholder="请输入内容"
style="width: 98%"
/>
</div>
</div>
<div>
<div>原因分析</div>
<div>
<el-input
v-model="formData.reasonAnalysis"
:rows="3"
type="textarea"
placeholder="请输入内容"
style="width: 98%"
/>
</div>
</div>
</div>
</div>
<div class="report-content-part5">
<div><span>工程签证情况</span></div>
<div>
<div>
<div><span>专题报告例会纪要</span></div>
<div>
<el-input
v-model="formData.meetingSummary"
:rows="3"
type="textarea"
placeholder="请输入内容"
style="width: 95%"
/>
</div>
<div><span>内容简要</span></div>
<div>
<el-input
v-model="formData.meetingContentBriefly"
:rows="3"
type="textarea"
placeholder="请输入内容"
style="width: 95%"
/>
</div>
</div>
<div>
<div><span>工程质量签证</span></div>
<div>
<el-input
v-model="formData.engineeringQualityVisa"
:rows="3"
type="textarea"
placeholder="请输入内容"
style="width: 95%"
/>
</div>
<div><span>内容简要</span></div>
<div>
<el-input
v-model="formData.engineeringContentBriefly"
:rows="3"
type="textarea"
placeholder="请输入内容"
style="width: 95%"
/>
</div>
</div>
<div>
<div><span>向施工单位发出的通知指示指令</span></div>
<div>
<el-input v-model="formData.instructions" :rows="3" type="textarea" placeholder="请输入内容" style="width: 95%" />
</div>
<div><span>内容简要</span></div>
<div>
<el-input
v-model="formData.instructionsContentBriefly"
:rows="3"
type="textarea"
placeholder="请输入内容"
style="width: 95%"
/>
</div>
</div>
<div>
<div><span>施工单位提出的各种报告</span></div>
<div>
<el-input v-model="formData.presentation" :rows="3" type="textarea" placeholder="请输入内容" style="width: 95%" />
</div>
<div><span>内容简要</span></div>
<div>
<el-input
v-model="formData.presentationContentBriefly"
:rows="3"
type="textarea"
placeholder="请输入内容"
style="width: 95%"
/>
</div>
</div>
<div>
<div><span>工程付款签证</span></div>
<div>
<el-input
v-model="formData.projectPaymentVisa"
:rows="3"
type="textarea"
placeholder="请输入内容"
style="width: 95%"
/>
</div>
<div><span>内容简要</span></div>
<div>
<el-input
v-model="formData.projectPaymentContentBriefly"
:rows="3"
type="textarea"
placeholder="请输入内容"
style="width: 95%"
/>
</div>
</div>
</div>
</div>
<div class="report-content-step">
<div class="step-title">工程进度</div>
<div class="step-sub-title">本月完成情况</div>
<div class="step-input">
<el-input v-model="formData.thisMonthCompletion" :rows="3" type="textarea" placeholder="请输入内容" />
</div>
<div class="step-sub-title">下月计划完成</div>
<div class="step-input">
<el-input v-model="formData.nextMonthPlan" :rows="3" type="textarea" placeholder="请输入内容" />
</div>
</div>
<div class="report-content-step">
<div class="step-title">工程质量</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.constructionQuality" :rows="3" type="textarea" placeholder="请输入内容" />
</div>
</div>
<div class="report-content-step">
<div class="step-title">安全环保文明生产</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.civilizationContent" :rows="3" type="textarea" placeholder="请输入内容" />
</div>
</div>
<div class="report-content-step">
<div class="step-title">费用支付</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.costContent" :rows="3" type="textarea" placeholder="请输入内容" />
</div>
</div>
<div class="report-content-step">
<div class="step-title">合同管理</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.contractManagement" :rows="3" type="textarea" placeholder="请输入内容" />
</div>
</div>
<div class="report-content-step">
<div class="step-title">存在的问题</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.existingProblems" :rows="3" type="textarea" placeholder="请输入内容" />
</div>
</div>
<div class="report-content-step">
<div class="step-title">监理工作小结</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.workSummary" :rows="3" type="textarea" placeholder="请输入内容" />
</div>
</div>
<div class="report-content-step">
<div class="step-title">下月工作计划</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.nextMonthWorkPlan" :rows="3" type="textarea" placeholder="请输入内容" />
</div>
</div>
<div class="report-content-step">
<div class="step-title">本月大事记</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.thisMonthEventsRecord" :rows="3" type="textarea" placeholder="请输入内容" />
</div>
</div>
<div class="report-content-img">
<div class="step-title">工程照片</div>
<div class="img-list">
<img :src="item.url" alt="" srcset="" v-for="(item, index) in fileList" :key="index" />
<div class="face-img">
<el-upload
class="face-uploader"
:action="`${baseUrl}` + '/xmgl/file/upload'"
:show-file-list="false"
:on-success="(response, uploadFile) => handleAvatarSuccess(response, uploadFile)"
accept="image/jpg, image/jpeg, image/png"
>
<el-icon><plus /></el-icon>
</el-upload>
</div>
</div>
</div>
</div>
<template #footer>
<div>
<el-button type="primary" @click="submitReport">提交月报</el-button>
<el-button type="primary" @click="submitPrint">提交打印</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
import { onMounted, ref, watch, reactive } from "vue";
import type { UploadProps } from "element-plus";
import { ElMessage, ElMessageBox } from "element-plus";
import { submitMonthlyReport } from "@/api/modules/project";
import printJS from "print-js";
const fileList = ref([]);
const baseUrl = import.meta.env.VITE_API_URL;
const props = defineProps({
addVisible: Boolean,
searchSn: String,
activeValue: String
});
const emits = defineEmits(["update:addVisible"]);
const formData = ref<any>({
stage: "",
signOpinion: "",
actualCompletion: "",
reasonAnalysis: "",
meetingSummary: "",
meetingContentBriefly: "",
engineeringQualityVisa: "",
engineeringContentBriefly: "",
instructions: "",
instructionsContentBriefly: "",
presentation: "",
presentationContentBriefly: "",
projectPaymentVisa: "",
projectPaymentContentBriefly: "",
thisMonthCompletion: "",
nextMonthPlan: "",
constructionQuality: "",
civilizationContent: "",
costContent: "",
contractManagement: "",
existingProblems: "",
workSummary: "",
nextMonthWorkPlan: "",
thisMonthEventsRecord: "",
imageFiles: ""
});
const visible1 = ref(false);
//
const submitPrint = async () => {
printJS({
printable: "monthlyReport",
type: "html",
targetStyles: ["*"],
maxWidth: 2500,
style: "@page{size:auto; margin: 0;}" + "@media print { @page {size: landscape } }"
});
};
//
const submitReport = async () => {
let requestData = {
...formData.value
};
if (!requestData.stage) {
ElMessage.error("请输入月报期数");
return;
}
if (props.activeValue == "eng") {
requestData.engineeringSn = props.searchSn;
} else {
requestData.projectSn = props.searchSn;
}
if (fileList.value.length > 0) {
let str = "";
fileList.value.map((item, index) => {
if (index == fileList.value.length) {
str += item.url;
} else {
str = str + item.url + ",";
}
});
requestData.imageFiles = str;
}
const res = await submitMonthlyReport(requestData);
if (res.success) {
ElMessage.success("操作成功");
visible1.value = false;
}
};
//
const handleAvatarSuccess: UploadProps["onSuccess"] = (response, uploadFile) => {
console.log(response.result.url);
console.log(response, uploadFile);
fileList.value.push({ name: response.result.originalFilename, url: response.result.url });
};
const validatorNumber = (e: any, key: any) => {
//
let pattern = /^\d+$/;
let dataValue = formData.value[key];
if (!pattern.test(dataValue)) {
ElMessage.error("请输入正整数");
formData.value[key] = "";
}
};
//
const closeMain = () => {
visible1.value = false;
};
watch(
() => props.addVisible,
n => {
if (n) {
visible1.value = n;
}
}
);
watch(
() => visible1,
n => {
emits("update:addVisible", n);
}
);
onMounted(() => {});
</script>
<style lang="scss" scoped>
@mixin flex {
display: flex;
align-items: center;
}
@mixin title {
font-size: 14px;
font-family: Source Han Sans CN-Regular, Source Han Sans CN;
font-weight: 400;
color: #333333;
border-left: 2px solid #008bff;
padding-left: 5px;
}
.overview {
:deep() {
.el-dialog__body {
padding-top: 0;
padding-bottom: 0;
}
}
.title-detail {
@include flex;
border-left: 3px solid #0f81ff;
> span {
font-family: Source Han Sans CN-Regular, Source Han Sans CN;
font-weight: 400;
color: #333333;
margin-left: 12px;
margin-right: auto;
font-size: 18px;
}
:deep(.el-icon) {
cursor: pointer;
color: #a8abb2;
}
}
.report-content {
.title {
font-size: 23px;
font-family: PingFang SC-Semibold, PingFang SC;
font-weight: 600;
color: #333333;
text-align: center;
}
.sub-title {
@include flex;
justify-content: center;
font-size: 18px;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #333333;
}
.sub-title:nth-child(3) {
margin-top: 9px;
}
.sub-title:nth-child(4) {
margin-top: 18px;
}
.title:nth-child(5) {
margin-top: 25px;
}
.engineer-name {
font-size: 16px;
font-family: PingFang SC-Semibold, PingFang SC;
font-weight: 600;
color: #333333;
margin-top: 11px;
}
&-part1 {
padding: 16px 9px;
border: 1px solid #dedede;
margin-top: 11px;
div {
font-size: 16px;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
}
div:last-child {
text-align: right;
}
div:not(:last-child) {
margin-bottom: 20px;
}
div:nth-child(6) {
margin-bottom: 0px;
}
}
&-part2 {
padding: 16px 9px;
border: 1px solid #dedede;
border-top: 0;
div:nth-child(1) {
font-size: 16px;
font-family: PingFang SC-Semibold, PingFang SC;
font-weight: 600;
color: #333333;
margin-bottom: 14px;
}
div:nth-child(3) {
@include flex;
justify-content: flex-end;
span {
white-space: nowrap;
}
span:first-child {
margin-right: 120px;
}
span:nth-child(2) {
margin-right: 60px;
}
span:last-child {
margin-right: 107px;
}
}
}
&-part3 {
border: 1px solid #dedede;
border-top: 0;
> div {
@include flex;
height: 50px;
> div {
height: 50px;
line-height: 50px;
}
> div:nth-child(2n-1) {
width: 15%;
text-align: center;
}
> div:nth-child(2n) {
width: 35%;
text-indent: 1em;
}
}
> div:nth-child(1) {
> div:not(:last-child) {
border-right: 1px solid #dedede;
border-bottom: 1px solid #dedede;
}
> div:nth-child(4) {
border-bottom: 1px solid #dedede;
}
}
> div:nth-child(2) {
> div:not(:last-child) {
border-right: 1px solid #dedede;
}
}
}
&-part4 {
@include flex;
border: 1px solid #dedede;
border-top: 0;
height: 200px;
> div:nth-child(1) {
@include flex;
justify-content: center;
align-items: center;
width: 3%;
height: 200px;
border-right: 1px solid #dedede;
> span {
display: inline-block;
writing-mode: vertical-lr;
letter-spacing: 4px;
}
}
> div:nth-child(2) {
width: 97%;
> div {
height: 100px;
@include flex;
> div:nth-child(1) {
@include flex;
justify-content: center;
width: calc(12% + 3px);
height: 100%;
border-right: 1px solid #dedede;
border-bottom: 1px solid #dedede;
}
> div:nth-child(2) {
@include flex;
justify-content: center;
flex: 1;
height: 100%;
border-bottom: 1px solid #dedede;
}
}
}
}
&-part5 {
@include flex;
border: 1px solid #dedede;
border-top: 0;
height: 500px;
> div:nth-child(1) {
@include flex;
justify-content: center;
width: 3%;
height: 100%;
border-right: 1px solid #dedede;
> span {
display: inline-block;
writing-mode: vertical-lr;
letter-spacing: 4px;
}
}
> div:nth-child(2) {
width: 97%;
height: 100%;
> div {
height: 100px;
@include flex;
> div:nth-child(2n-1) {
@include flex;
justify-content: center;
width: calc(12% + 3px);
height: 100%;
border-right: 1px solid #dedede;
border-bottom: 1px solid #dedede;
> span {
display: inline-block;
width: 92%;
text-align: center;
}
}
> div:nth-child(2n) {
@include flex;
justify-content: center;
flex: 1;
height: 100%;
border-bottom: 1px solid #dedede;
}
> div:nth-child(3) {
border-left: 1px solid #dedede;
}
}
}
}
&-step {
border: 1px solid #dedede;
border-top: 0;
padding: 14px 23px;
.step-title {
font-size: 16px;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #000000;
}
.step-sub-title {
font-size: 16px;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #000000;
margin-top: 17px;
margin-bottom: 9px;
}
}
&-img {
border: 1px solid #dedede;
border-top: 0;
padding: 14px 23px;
.step-title {
font-size: 16px;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #000000;
margin-bottom: 12px;
}
.img-list {
@include flex;
img {
width: 100px;
height: 100px;
border: 1px solid #ccc;
margin-right: 15px;
}
}
.face-img {
:deep(.face-uploader .el-upload) {
border: 2px dashed #d9d9d9 !important;
cursor: pointer !important;
position: relative !important;
overflow: hidden !important;
}
.face-uploader .el-upload:hover {
border-color: #409eff !important;
}
:deep(.el-icon) {
font-size: 42px;
color: #8c939d;
width: 96px;
height: 96px;
line-height: 53px;
text-align: center;
}
}
}
}
}
</style>

View File

@ -3,22 +3,18 @@
<el-dialog :show-close="false" v-model="visible1" width="1305px" @close="closeMain">
<template #title>
<div class="title-detail">
<span>新增月报</span>
<span>月报详情</span>
<el-icon>
<close @click="closeMain" />
</el-icon>
</div>
</template>
<div class="report-content">
<div class="report-content" id="monthlyReport">
<div class="title">天地一号御花园工程项目</div>
<div class="title">建设监理工作月报</div>
<div class="sub-title">
<span></span>
<el-input
v-model.number="formData.number"
style="width: 60px; margin: 0 5px"
@blur="e => validatorPhone(e, 'number')"
/>
<span>{{ formData.stage }}1</span>
<span></span>
</div>
<div class="sub-title">天眼监理工程有限公司项目监理部</div>
@ -39,7 +35,7 @@
<div class="report-content-part2">
<div>项目监理部总监理工程师签认意见</div>
<div>
<el-input v-model="formData.advice" :rows="3" type="textarea" />
<span>{{ formData.signOpinion }}</span>
</div>
<div>
<span>总监理工程师</span>
@ -67,13 +63,13 @@
<div>
<div><span>实际完成</span></div>
<div>
<el-input v-model="formData.advice" :rows="3" type="textarea" placeholder="请输入内容" style="width: 98%" />
<span>{{ formData.actualCompletion }}</span>
</div>
</div>
<div>
<div>原因分析</div>
<div>
<el-input v-model="formData.advice" :rows="3" type="textarea" placeholder="请输入内容" style="width: 98%" />
<span>{{ formData.reasonAnalysis }}</span>
</div>
</div>
</div>
@ -84,51 +80,51 @@
<div>
<div><span>专题报告例会纪要</span></div>
<div>
<el-input v-model="formData.advice" :rows="3" type="textarea" placeholder="请输入内容" style="width: 95%" />
<span>{{ formData.meetingSummary }}</span>
</div>
<div><span>内容简要</span></div>
<div>
<el-input v-model="formData.advice" :rows="3" type="textarea" placeholder="请输入内容" style="width: 95%" />
<span>{{ formData.meetingContentBriefly }}</span>
</div>
</div>
<div>
<div><span>工程质量签证</span></div>
<div>
<el-input v-model="formData.advice" :rows="3" type="textarea" placeholder="请输入内容" style="width: 95%" />
<span>{{ formData.engineeringQualityVisa }}</span>
</div>
<div><span>内容简要</span></div>
<div>
<el-input v-model="formData.advice" :rows="3" type="textarea" placeholder="请输入内容" style="width: 95%" />
<span>{{ formData.engineeringContentBriefly }}</span>
</div>
</div>
<div>
<div><span>向施工单位发出的通知指示指令</span></div>
<div>
<el-input v-model="formData.advice" :rows="3" type="textarea" placeholder="请输入内容" style="width: 95%" />
<span>{{ formData.instructions }}</span>
</div>
<div><span>内容简要</span></div>
<div>
<el-input v-model="formData.advice" :rows="3" type="textarea" placeholder="请输入内容" style="width: 95%" />
<span>{{ formData.instructionsContentBriefly }}</span>
</div>
</div>
<div>
<div><span>施工单位提出的各种报告</span></div>
<div>
<el-input v-model="formData.advice" :rows="3" type="textarea" placeholder="请输入内容" style="width: 95%" />
<span>{{ formData.presentation }}</span>
</div>
<div><span>内容简要</span></div>
<div>
<el-input v-model="formData.advice" :rows="3" type="textarea" placeholder="请输入内容" style="width: 95%" />
<span>{{ formData.presentationContentBriefly }}</span>
</div>
</div>
<div>
<div><span>工程付款签证</span></div>
<div>
<el-input v-model="formData.advice" :rows="3" type="textarea" placeholder="请输入内容" style="width: 95%" />
<span>{{ formData.projectPaymentVisa }}</span>
</div>
<div><span>内容简要</span></div>
<div>
<el-input v-model="formData.advice" :rows="3" type="textarea" placeholder="请输入内容" style="width: 95%" />
<span>{{ formData.projectPaymentContentBriefly }}</span>
</div>
</div>
</div>
@ -137,85 +133,72 @@
<div class="step-title">工程进度</div>
<div class="step-sub-title">本月完成情况</div>
<div class="step-input">
<el-input v-model="formData.advice" :rows="3" type="textarea" />
<span>{{ formData.thisMonthCompletion }}</span>
</div>
<div class="step-sub-title">下月计划完成</div>
<div class="step-input">
<el-input v-model="formData.advice" :rows="3" type="textarea" />
<span>{{ formData.nextMonthPlan }}</span>
</div>
</div>
<div class="report-content-step">
<div class="step-title">工程质量</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.advice" :rows="3" type="textarea" />
<span>{{ formData.constructionQuality }}</span>
</div>
</div>
<div class="report-content-step">
<div class="step-title">安全环保文明生产</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.advice" :rows="3" type="textarea" />
<span>{{ formData.civilizationContent }}</span>
</div>
</div>
<div class="report-content-step">
<div class="step-title">费用支付</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.advice" :rows="3" type="textarea" />
<span>{{ formData.costContent }}</span>
</div>
</div>
<div class="report-content-step">
<div class="step-title">合同管理</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.advice" :rows="3" type="textarea" />
<span>{{ formData.contractManagement }}</span>
</div>
</div>
<div class="report-content-step">
<div class="step-title">存在的问题</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.advice" :rows="3" type="textarea" />
<span>{{ formData.existingProblems }}</span>
</div>
</div>
<div class="report-content-step">
<div class="step-title">监理工作小结</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.advice" :rows="3" type="textarea" />
<span>{{ formData.workSummary }}</span>
</div>
</div>
<div class="report-content-step">
<div class="step-title">下月工作计划</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.advice" :rows="3" type="textarea" />
<span>{{ formData.nextMonthWorkPlan }}</span>
</div>
</div>
<div class="report-content-step">
<div class="step-title">本月大事记</div>
<div class="step-input" style="margin-top: 11px">
<el-input v-model="formData.advice" :rows="3" type="textarea" />
<span>{{ formData.thisMonthEventsRecord }}</span>
</div>
</div>
<div class="report-content-img">
<div class="step-title">本月大事记</div>
<div class="step-title">工程照片</div>
<div class="img-list">
<img src="" alt="" srcset="" />
<img src="" alt="" srcset="" />
<div class="face-img">
<el-upload
class="face-uploader"
:action="`${baseUrl}` + '/xmgl/file/upload'"
:show-file-list="false"
:on-success="(response, uploadFile) => handleAvatarSuccess(response, uploadFile)"
accept="image/jpg, image/jpeg, image/png"
>
<el-icon><plus /></el-icon>
</el-upload>
</div>
<img :src="item.url" alt="" srcset="" v-for="(item, index) in fileList" :key="index" />
</div>
</div>
</div>
<template #footer>
<div>
<el-button type="primary" @click="visible1 = false">提交月报</el-button>
<el-button type="primary" @click="visible1 = false">提交打印</el-button>
<el-button type="primary" @click="submitReport">提交月报</el-button>
<el-button type="primary" @click="submitPrint">提交打印</el-button>
</div>
</template>
</el-dialog>
@ -226,28 +209,82 @@
import { onMounted, ref, watch, reactive } from "vue";
import type { UploadProps } from "element-plus";
import { ElMessage, ElMessageBox } from "element-plus";
import { submitMonthlyReport } from "@/api/modules/project";
import printJS from "print-js";
const fileList = ref([]);
const baseUrl = import.meta.env.VITE_API_URL;
const props = defineProps({
addVisible: Boolean
detailVisible: Boolean,
searchSn: String,
activeValue: String
});
const emits = defineEmits(["update:addVisible"]);
const emits = defineEmits(["update:detailVisible"]);
const formData = ref<any>({
number: "",
advice: ""
stage: "",
signOpinion: "",
actualCompletion: "",
reasonAnalysis: "",
meetingSummary: "",
meetingContentBriefly: "",
engineeringQualityVisa: "",
engineeringContentBriefly: "",
instructions: "",
instructionsContentBriefly: "",
presentation: "",
presentationContentBriefly: "",
projectPaymentVisa: "",
projectPaymentContentBriefly: "",
thisMonthCompletion: "",
nextMonthPlan: "",
constructionQuality: "",
civilizationContent: "",
costContent: "",
contractManagement: "",
existingProblems: "",
workSummary: "",
nextMonthWorkPlan: "",
thisMonthEventsRecord: ""
});
const visible1 = ref(true);
//
const handleAvatarSuccess: UploadProps["onSuccess"] = (response, uploadFile) => {
console.log(response.result.url);
console.log(response, uploadFile);
//
const submitPrint = async () => {
printJS({
printable: "monthlyReport",
type: "html",
targetStyles: ["*"],
maxWidth: 2500,
style: "@page{size:auto; margin: 0;}" + "@media print { @page {size: landscape } }"
});
};
const validatorPhone = (e: any, key: any) => {
//
let pattern = /^\d+$/;
let dataValue = formData.value[key];
if (!pattern.test(dataValue)) {
ElMessage.error("请输入正确的手机号码");
formData.value[key] = "";
//
const submitReport = async () => {
let requestData = {
...formData.value
};
if (!requestData.stage) {
ElMessage.error("请输入月报期数");
return;
}
if (props.activeValue == "eng") {
requestData.engineeringSn = props.searchSn;
} else {
requestData.projectSn = props.searchSn;
}
if (fileList.value.length > 0) {
let str = "";
fileList.value.map((item, index) => {
if (index == fileList.value.length) {
str += item.url;
} else {
str = str + item.url + ",";
}
});
requestData.imageFiles = str;
}
const res = await submitMonthlyReport(requestData);
if (res.success) {
ElMessage.success("操作成功");
visible1.value = false;
}
};
//
@ -255,7 +292,7 @@ const closeMain = () => {
visible1.value = false;
};
watch(
() => props.addVisible,
() => props.detailVisible,
n => {
if (n) {
visible1.value = n;
@ -265,7 +302,7 @@ watch(
watch(
() => visible1,
n => {
emits("update:addVisible", n);
emits("update:detailVisible", n);
}
);
onMounted(() => {});
@ -373,6 +410,9 @@ onMounted(() => {});
div:nth-child(3) {
@include flex;
justify-content: flex-end;
span {
white-space: nowrap;
}
span:first-child {
margin-right: 120px;
}

View File

@ -24,7 +24,19 @@
</template>
</ProTable>
<!-- 新增月报 -->
<add v-model:addVisible="addVisible" @confirm="confirmAdd"></add>
<monthlyAdd
v-model:addVisible="addVisible"
:searchSn="searchSn"
:activeValue="activeValue"
@confirm="confirmAdd"
></monthlyAdd>
<!-- 月报详情 -->
<monthlyDetails
v-model:detailVisible="detailVisible"
:searchSn="searchSn"
:activeValue="activeValue"
@confirm="confirmAdd"
></monthlyDetails>
<!-- 侧边栏选择 -->
<engineeringEngDrawer v-model="engVisable" :active="activeValue" ref="engDrawer" :engList="engList" @select="tabsSelect">
<template #default="{ data }">
@ -46,7 +58,9 @@ import { getRelevanceList } from "@/api/modules/common";
import engineeringEngDrawer from "@/components/engineeringEngDrawer/index.vue";
import allEngineering from "@/components/allEngineering/index.vue";
import { towerCraneEquipDel, towerCraneEquipPage, getEngineeringName } from "@/api/modules/project";
import add from "./components/add.vue";
import monthlyAdd from "./components/monthlyAdd.vue";
import monthlyDetails from "./components/monthlyDetails.vue";
const detailVisible = ref(false);
const addVisible = ref(false);
const activeValue = ref("eng");
const engList = ref([]);

View File

@ -488,6 +488,7 @@ onMounted(() => {});
box-shadow: 0px 4px 8px 0px rgba(48, 62, 100, 0.2);
border-radius: 8px 8px 8px 8px;
padding: 15px 20px;
overflow: hidden;
.content-title {
@include title;
margin-top: 45px;

View File

@ -488,6 +488,7 @@ onMounted(() => {});
box-shadow: 0px 4px 8px 0px rgba(48, 62, 100, 0.2);
border-radius: 8px 8px 8px 8px;
padding: 15px 20px;
overflow: hidden;
.content-title {
@include title;
margin-top: 45px;