目錄
- 引言
- 博文系列
- 專案簡介
- 效果圖
- 開發環境
- 專案風格
- 資料表結構
- 專案結構
- 后端結構
- 前端結構
- 專案難點
- 前端難點
- 后端難點
- 核心原始碼
- 前端原始碼
- 添加路由
- 添加左側選單顯示
- 后端原始碼
- 下載鏈接
- 博主寄語
引言
Hello,我是Bug終結者,一名熱愛后端Java的風趣且幽默的程式員~ 終于等到幸運的你~
快來發現我的宇宙哦~

博文系列
🚀深入淺出前后端分離系列第一篇 :前后端分離 — 深入淺出Spring Boot + Vue實作員工管理系統 Vue如此簡單~
🚀深入淺出前后端分離系列第二篇 :前后端分離 – 深入淺出 Spring Boot + Vue + ElementUI 實作相冊管理系統【檔案上傳 分頁 】 檔案上傳也不過如此~
專案簡介
在建筑專案中,進度是以金額來計算的,比如,專案合同金額為10000萬元,哪一個進度完成那一部分金額,在次基礎上,建立出一套工程建筑專案管理系統
功能細節
實作專案的增刪改和串列
- 專案的串列需要支持分頁和按照專案名稱進行多條件查詢
- 專案全稱和簡稱均不能重復
- 專案串列原型如下:

點擊專案簡稱可以查看專案詳情頁面

點擊進度進入該專案的進度串列頁面
實作專案進度填報功能
- 實作進度填報的新增、編輯、洗掉和串列功能
- 串列頁面效果如下
*
進度年份和月份必須在專案的開始和結束時間之間,可以包括開始和結束的月份
進度的總完成金額不能超過專案的合同額度,
效果圖

開發環境
后端:Spring Boot + MyBatis + Maven
前端:Vue + ElementUI
工具:前端使用VSCode,后端使用IDEA
🚀放松一下~

夠給力的~

哇哦~🥰
💗💗💗
專案風格
🚀請求方式統一為Post請求,目的是保證安全性
規范了介面層統一回傳格式為ResultBean,詳細如:
統一回傳格式風格類,ResultBean
狀態碼,詳細資訊,資料
資料表結構
t_project專案表
DROP TABLE IF EXISTS t_project;
CREATE TABLE `t_project` (
`noid` INT(11) NOT NULL AUTO_INCREMENT,
`full_name` VARCHAR(128) NOT NULL COMMENT '專案全稱名稱',
`simple_name` VARCHAR(128) NOT NULL COMMENT '專案簡稱',
contract_money DECIMAL(12,2) DEFAULT 0 COMMENT '合同金額',
province_id CHAR(8) NOT NULL COMMENT '所屬省份',
important_level TINYINT(4) DEFAULT 1 COMMENT '重要級別, 1 普通專案;2 重要專案',
start_time DATETIME NOT NULL COMMENT '專案開始時間',
end_time DATETIME NOT NULL COMMENT '專案結束時間',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
PRIMARY KEY (`noid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
t_province省份表
DROP TABLE IF EXISTS `t_province`;
CREATE TABLE `t_province` (
`noid` char(8) NOT NULL,
`province_name` varchar(64) DEFAULT NULL,
`order_numb` int(11) NOT NULL DEFAULT '100' COMMENT '順序號',
PRIMARY KEY (`noid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
insert into `t_province`(`noid`,`province_name`,`order_numb`) values ('1','北京市',10),('10','江蘇省',100),('11','浙江省',110),('12','安徽省',120),('13','福建省',130),('14','江西省',140),('15','山東省',150),('16','河南省',160),('17','湖北省',170),('18','湖南省',180),('19','廣東省',190),('2','天津市',20),('20','廣西省',200),('21','海南省',210),('22','重慶市',220),('23','四川省',230),('24','貴州省',240),('25','云南省',250),('26','西藏',260),('27','陜西省',270),('28','甘肅省',280),('29','青海省',290),('3','河北省',30),('30','寧夏省',300),('31','新疆',310),('32','臺灣省',320),('33','香港特別行政區',330),('34','澳門',340),('4','山西省',40),('5','內蒙古',50),('6','遼寧省',60),('7','吉林省',70),('8','黑龍江省',80),('9','上海市',90);
t_project_month_progress 專案月進度表
DROP TABLE IF EXISTS t_project_month_progress;
CREATE TABLE `t_project_month_progress` (
`noid` int(11) NOT NULL AUTO_INCREMENT,
`project_id` int(11) NOT NULL COMMENT '專案id',
`progress_year` int(11) NOT NULL COMMENT '進度年份',
`progress_month` int(11) NOT NULL COMMENT '進度月份',
`progress_money` decimal(12,2) NOT NULL DEFAULT '0.00' COMMENT '當月進度完成金額',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
PRIMARY KEY (`noid`),
UNIQUE KEY `unq_project_year_month` (`project_id`,`progress_year`,`progress_month`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
專案結構
后端結構

前端結構

專案難點
前端難點
在選擇月份的時候要求選擇的月份不可大于專案開始月份也不可小于專案結束月份
在ElementUI el-datepicker組件中可顯示能被選中的月份,如下

這種效果該如何實作呢
采用組件所帶的picker-options屬性實作日期過濾
<el-form-item label="進度日期">
<el-date-picker type="month" size="mini" :picker-options="pickerOptions" value-format="yyyy-MM" v-model="projectMonthProgress.progress_time" placeholder="選擇進度日期"></el-date-picker>
</el-form-item>
js代碼
//該代碼寫在data中,動態加載到組件中
pickerOptions:{
//計算該日期是否可選,true,不可選,false,可選
disabledDate: (time) => {
let start = time.getTime() < new Date(this.project.start_time).getTime();
let end = time.getTime() > new Date(this.project.end_time).getTime();
return start || end;
}
}
至此,控制日期可選完美解決
后端難點
在專案串列、專案月份進度頁、專案詳情頁需要顯示當前專案的完成額度與未完成額度,從資料庫讀出,在project類中添加冗余欄位,并回傳給前端從而進行展示資料,每次加載都去請求后端進行更新資料
核心原始碼
前端原始碼
ProjectList.vue
<template xmlns:c="http://www.w3.org/1999/html">
<div class="box-main2 box-heigt100">
<div class="box-search">
<div>
<el-input type="text" size="mini" @keydown.native.enter="clkBtnSearch" @clear="clkBtnSearch" v-model="searchInfo.searchKey" clearable placeholder="請輸入標題"></el-input>
</div>
<div class="m1">
<el-button type="primary" size="mini" @click="clkBtnSearch">搜索</el-button>
</div>
<div class="m1">
<el-button type="warning" size="mini" @click="clkBtnAdd">新增</el-button>
</div>
</div>
<div class="box-table2">
<el-table :data="projectPage.list" >
<el-table-column type="index" label="序號" width="50"></el-table-column>
<el-table-column label="專案簡稱" width="120">
<template slot-scope="scope">
<el-link type="primary" style="color: #409EFF;" @click="clkBtnGoDetail(scope.row)">{{scope.row.simple_name}}</el-link>
</template>
</el-table-column>
<el-table-column prop="str_province" label="所屬省份" width="80"></el-table-column>
<el-table-column prop="contract_money" label="合同金額(萬元)" width="150"></el-table-column>
<el-table-column prop="done_money" label="已完成金額(萬元)" width="150">
<template slot-scope="scope">
<span v-if="scope.row.done_money == null">--</span>
<span v-if="scope.row.done_money != null">{{scope.row.done_money}}</span>
</template>
</el-table-column>
<el-table-column prop="incomplete_money" label="未完成金額(萬元)">
<template slot-scope="scope">
<span v-if="scope.row.incomplete_money == null">--</span>
<span v-if="scope.row.incomplete_money != null">{{scope.row.incomplete_money}}</span>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" @click="clkBtnGotoProgress(scope.row)" size="mini">進度</el-button>
<el-button type="warning" @click="clkBtnEdit(scope.row)" size="mini">修改</el-button>
<el-button type="danger" @click="clkBtnDelete(scope.row)" size="mini">洗掉</el-button>
</template>
</el-table-column>
</el-table>
</div>
<div class="box-page1">
<el-pagination background :current-page="projectPage.pageNum" :page-size="projectPage.pageSize" :total="projectPage.total"
layout="total,prev,pager,next"
@current-change="chgPageNum">
</el-pagination>
</div>
<el-dialog :visible.sync="showProjectDigLog" title="新增/編輯">
<el-form label-width="120px">
<el-form-item label="專案全稱">
<el-input type="text" size="mini" placeholder="請輸入專案全稱" v-model="project.full_name"></el-input>
</el-form-item>
<el-form-item label="專案簡稱">
<el-input type="text" size="mini" placeholder="請輸入專案簡稱" v-model="project.simple_name"></el-input>
</el-form-item>
<el-form-item label="所屬省份">
<el-select v-model="project.province_id" placeholder="請選擇" size="mini">
<el-option
v-for="item in provinceList"
:key="item.noid"
:label="item.province_name"
:value="item.noid">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="合同金額">
<el-input v-model="project.contract_money" size='mini'>
<template slot="append">萬元</template>
</el-input>
</el-form-item>
<el-form-item label="重要級別">
<el-radio-group v-model="project.important_level">
<el-radio :label="1">普通專案</el-radio>
<el-radio :label="2">重要專案</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="開始日期">
<el-date-picker v-model="project.start_time" value-format="yyyy-MM-dd hh:mm:ss" placeholder="開始日期"></el-date-picker>
</el-form-item>
<el-form-item label="結束日期">
<el-date-picker v-model="project.end_time" value-format="yyyy-MM-dd hh:mm:ss" placeholder="結束日期"></el-date-picker>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" size="mini" @click="clkBtnSave">確定</el-button>
<el-button type="warning" size="mini" @click="showProjectDigLog = false">取消</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import request from '@/common/utils/request';
export default {
computed:{
},
inject: ['reload'],
data() {
return {
searchInfo: {searchKey:''},
projectPage:{pageNum: 1, pageSize: 2, list: []},
showProjectDigLog:false,
project:{},
provinceList:[],
};
},
watch:{
'$route.path':{
handler:function(newVal){
if(newVal == '/picture-list'){
this.initData();
}
}, immediate: true
},
},
mounted() {
this.initData();
},
methods: {
initData() {
this.getProvinceList();
this.getProjectList();
},
getProvinceList() {
let url = this.settings.apiUrl + "/springbootajax/province/list";
let data = {};
request.post(url, data).then((res) => {
if (res.code === 0) {
this.provinceList = res.data;
}
})
},
getProjectList() {
let url = this.settings.apiUrl + "/springbootajax/project/page";
let data = {};
data.searchKey = this.searchInfo.searchKey;
data.pageNum = this.projectPage.pageNum;
data.pageSize = this.projectPage.pageSize;
request.post(url, data).then((res) => {
if (res.code === 0) {
this.projectPage = res.data;
console.log(this.projectPage)
}
})
},
clkBtnDelete(row) {
this.$confirm("您確信要洗掉嗎?", "提示").then(() => {
let url = this.settings.apiUrl + "/springbootajax/project/delete";
let data = {noid: row.noid};
request.post(url, data).then((res) => {
if (res.code === 0) {
this.getProjectList();
this.$message("洗掉成功~");
}
})
}).catch(() => {
this.$message("取消洗掉~");
})
},
clkBtnEdit(row) {
this.project = JSON.parse(JSON.stringify(row));
this.showProjectDigLog = true;
},
clkBtnSave() {
console.log(this.project)
let url = this.settings.apiUrl + "/springbootajax/project/save";
let data = this.project;
let options = {Headers:{'Content-type':'application/json'}};
request.post(url, data, options).then((res) => {
if (res.code === 0) {
this.getProjectList();
this.showProjectDigLog = false;
this.$message("保存成功~");
}
})
},
clkBtnAdd() {
this.project = {important_level:1};
this.showProjectDigLog = true;
},
clkBtnSearch() {
this.getProjectList();
},
chgPageNum(pageNum) {
this.projectPage.pageNum = pageNum;
this.getProjectList();
},
clkBtnGoDetail(row) {
this.$router.push({path:'/project-detail',query:{noid:row.noid}});
},
clkBtnGotoProgress(row) {
this.$router.push({path:'/project-month-progress',query:{noid:row.noid}});
}
},
};
</script>
<style lang="scss" scoped="scoped">
.box-main2 {
width: 90%;
margin: 10px;
box-table2{
height: auto;
}
.box-search{
display: flex;
margin: 10px;
.m1{
padding-left: 10px;
}
}
.box-page1{
margin-top: 10px;
}
}
</style>
ProjectDetail專案詳情頁
<template>
<div class="box-main2 box-heigt100">
<div class="detail">
<p>
<span>
<label>專案全稱:</label><b>{{project.full_name}}</b>
</span>
</p>
<p>
<span>
<label>專案簡稱:</label><b>{{project.simple_name}}</b>
</span>
</p>
<p>
<span>
<label>所屬省份:</label><b>{{project.str_province}}</b>
</span>
</p>
<p>
<span>
<label>重要級別:</label><b>{{project.important_level|filterImportant_level}}</b>
</span>
</p>
<p>
<span>
<label>專案起止:</label><b>{{project.start_time|filterDateFormat1}} -- {{project.end_time|filterDateFormat1}}</b>
</span>
</p>
<p>
<span>
<label>合同金額:</label><b>{{project.contract_money}}萬元</b>
</span>
</p>
<p>
<span>
<label>完成額度:</label><b v-if="project.done_money == null">--</b><b v-if="project.done_money != null">{{project.done_money}}</b>
</span>
</p>
<p>
<span>
<label>未完成額度:</label><b v-if="project.incomplete_money == null">--</b><b v-if="project.incomplete_money != null">{{project.incomplete_money}}</b>
</span>
</p>
<div class="footer">
<el-button type="warning" size="mini" @click="clkBtnEdit">編輯專案資訊</el-button>
<el-button type="primary" size="mini" @click="clkBtnGotoProgress">進度串列</el-button>
<el-button type="info" size="mini" @click='clkBtnBackProject'>回傳專案串列</el-button>
</div>
<el-dialog :visible.sync="showProjectDigLog" title="新增/編輯">
<el-form label-width="120px">
<el-form-item label="專案全稱">
<el-input type="text" size="mini" placeholder="請輸入專案全稱" v-model="project.full_name"></el-input>
</el-form-item>
<el-form-item label="專案簡稱">
<el-input type="text" size="mini" placeholder="請輸入專案簡稱" v-model="project.simple_name"></el-input>
</el-form-item>
<el-form-item label="所屬省份">
<el-select v-model="project.province_id" placeholder="請選擇" size="mini">
<el-option
v-for="item in provinceList"
:key="item.noid"
:label="item.province_name"
:value="item.noid">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="合同金額">
<el-input v-model="project.contract_money" size='mini'>
<template slot="append">萬元</template>
</el-input>
</el-form-item>
<el-form-item label="重要級別">
<el-radio-group v-model="project.important_level">
<el-radio :label="1">普通專案</el-radio>
<el-radio :label="2">重要專案</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="開始日期">
<el-date-picker v-model="project.start_time" value-format="yyyy-MM-dd hh:mm:ss" placeholder="開始日期"></el-date-picker>
</el-form-item>
<el-form-item label="結束日期">
<el-date-picker v-model="project.end_time" value-format="yyyy-MM-dd hh:mm:ss" placeholder="結束日期"></el-date-picker>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" size="mini" @click="clkBtnSave">確定</el-button>
<el-button type="warning" size="mini" @click="showProjectDigLog = false">取消</el-button>
</span>
</el-dialog>
</div>
</div>
</template>
<script>
import request from '@/common/utils/request';
export default {
computed:{
},
inject: ['reload'],
data() {
return {
noid:'',
project:{},
provinceList:[],
showProjectDigLog:false
};
},
watch:{
// '$route.path':{
// handler:function(newVal){
// if(newVal == '/project-detail'){
// this.initData();
// }
// }, immediate: true
// },
},
mounted() {
this.noid = this.$route.query.noid;
this.initData();
},
methods: {
initData() {
this.getProject();
this.getProvinceList();
},
getProvinceList() {
let url = this.settings.apiUrl + "/springbootajax/province/list";
let data = {};
request.post(url, data).then((res) => {
if (res.code === 0) {
this.provinceList = res.data;
}
})
},
getProject() {
let url = this.settings.apiUrl + "/springbootajax/project/get";
let data = {noid: this.noid};
request.post(url, data).then((res) => {
if (res.code === 0) {
this.project = res.data;
}
})
},
clkBtnBackProject() {
this.$router.push("project-list");
this.reload();
},
clkBtnGotoProgress() {
this.$router.push({path:'/project-month-progress',query:{noid:this.noid}});
},
clkBtnEdit() {
this.project = JSON.parse(JSON.stringify(this.project));
this.showProjectDigLog = true;
},
clkBtnSave() {
console.log(this.project)
let url = this.settings.apiUrl + "/springbootajax/project/save";
let data = this.project;
let options = {Headers:{'Content-type':'application/json'}};
request.post(url, data, options).then((res) => {
if (res.code === 0) {
this.getProjectList();
this.showProjectDigLog = false;
this.$message("保存成功~");
}
})
}
},
filters:{
filterImportant_level(srcVal) {
if (srcVal == 1) {
return '普通專案';
} else {
return '重要專案';
}
},
filterDateFormat1(srcVal){
if(!srcVal){
return "";
}
if(srcVal.length<10){
return srcVal;
}
return srcVal.substr(0,10);
},
}
};
</script>
<style lang="scss" scoped="scoped">
.box-main2{
width:1100px;
margin:20px auto;
background: #fff;
.detail{
padding: 20px;
width:500px;
margin:0 auto;
}
}
</style>
ProjectMonthProgress 專案月份進度頁
<template>
<div class="box-main2 box-heigt100">
<div class="detail">
<p>
<span>
<label>專案簡稱:</label><b>{{project.simple_name}}</b>
</span>
 
<el-button type="warning" size="mini" @click='clkBtnGotoDetail'>專案詳情</el-button>
<el-button type="info" size="mini" @click='clkBtnBackProject'>回傳專案串列</el-button>
</p>
<p>
<span>
<label>合同金額:</label> <b>{{project.contract_money}}萬元</b>
</span>
<span>
<label>完成額度:</label> <b v-if="project.done_money == null">--</b><b v-if="project.done_money != null">{{project.done_money}}萬元</b>
</span>
<span>
<label>未完成額度:</label> <b v-if="project.incomplete_money == null">--</b><b v-if="project.incomplete_money != null">{{project.incomplete_money}}萬元</b>
</span>
</p>
<div class="box-main3">
<el-button type="primary" size="mini" @click="clkBtnAdd">新增進度</el-button>
<div class="box-table">
<el-table
:data="projectMonthProgressPage.list"
border
style="width: 100%">
<el-table-column header-align="center" align="center" type="index" label="序號" width="90"></el-table-column>
<el-table-column prop="progress_month" label="進度月份" >
</el-table-column>
<el-table-column header-align="center" align="center" prop="progress_money" label="完成額度(萬元)" >
</el-table-column>
<el-table-column header-align="center" align="center" label="操作" >
<template slot-scope="scope">
<span>
<el-button type="warning" @click="clkBtnEdit(scope.row)">編輯</el-button>
<el-button type="danger" @click="clkBtnDelete(scope.row)">洗掉</el-button>
</span>
</template>
</el-table-column>
</el-table>
</div>
</div>
<el-dialog title="新增/編輯" :visible.sync="showProgressDialog">
<el-form label-width="80px">
<el-form-item label="進度日期">
<el-date-picker type="month" size="mini" :picker-options="pickerOptions" value-format="yyyy-MM" v-model="projectMonthProgress.progress_time" placeholder="選擇進度日期"></el-date-picker>
</el-form-item>
<el-form-item label="完成額度">
<el-input size="mini" v-model="projectMonthProgress.progress_money" placeholder="請輸入完成的額度">
<template slot="append">萬元</template>
</el-input>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="showProgressDialog = false" size="mini">取 消</el-button>
<el-button type="primary" @click="clkBtnSave" size="mini">確 定</el-button>
</div>
</el-dialog>
<div class="box-page1">
<el-pagination background :current-page="projectMonthProgressPage.pageNum" :page-size="projectMonthProgressPage.pageSize" :total="projectMonthProgressPage.total"
layout="total,prev,pager,next"
@current-change="chgPageNum">
</el-pagination>
</div>
</div>
</div>
</template>
<script>
import request from '@/common/utils/request';
export default {
computed:{
},
inject: ['reload'],
data() {
return {
noid:'',
project:{},
showProgressDialog:false,
projectMonthProgress:{},
projectMonthProgressPage:{pageNum:1,pageSize:3, list:[]},
//規定可選擇的日期范圍,開始日期-結束日期之間
pickerOptions:{
disabledDate: (time) => {
let start = time.getTime() < new Date(this.project.start_time).getTime();
let end = time.getTime() > new Date(this.project.end_time).getTime();
return start || end;
}
}
};
},
watch:{
// '$route.path':{
// handler:function(newVal){
// if(newVal == '/project-month-progress'){
// this.initData();
// }
// }, immediate: true
// },
},
mounted() {
this.noid = this.$route.query.noid;
this.initData();
},
methods: {
initData() {
this.getProject();
this.getProjectMonthProgressList();
},
getProject() {
let url = this.settings.apiUrl + "/springbootajax/project/get";
let data = {noid: this.noid};
request.post(url, data).then((res) => {
if (res.code === 0) {
this.project = res.data;
}
})
},
getProjectMonthProgressList() {
let url = this.settings.apiUrl + "/springbootajax/project_month_progress/page";
let data = {};
data.pageNum = this.projectMonthProgressPage.pageNum;
data.pageSize = this.projectMonthProgressPage.pageSize;
request.post(url, data).then((res) => {
if (res.code === 0) {
this.projectMonthProgressPage = res.data;
console.log(res.data);
}
})
},
clkBtnBackProject() {
this.$router.push("project-list");
this.reload();
},
clkBtnGotoDetail() {
this.$router.push({path:'/project-detail',query:{noid:this.noid}});
},
clkBtnAdd() {
this.projectMonthProgress = {project_id:this.noid};
this.showProgressDialog = true;
},
clkBtnSave() {
let url = this.settings.apiUrl + "/springbootajax/project_month_progress/save";
let data = this.projectMonthProgress;
request.post(url, data).then((res) => {
if (res.code === 0) {
this.getProjectMonthProgressList();
this.showProgressDialog = false;
this.$message("保存成功~");
this.getProject();
}
})
},
chgPageNum(pageNum) {
this.projectMonthProgressPage.pageNum = pageNum;
this.getProjectMonthProgressList();
},
clkBtnEdit(row) {
this.projectMonthProgress = JSON.parse(JSON.stringify(row));
this.showProgressDialog = true;
},
clkBtnDelete(row) {
this.$confirm("您確信要洗掉嗎?", "提示").then(() => {
let url = this.settings.apiUrl + "/springbootajax/project_month_progress/delete";
let data = {noid: row.noid};
request.post(url, data).then((res) => {
if (res.code === 0) {
this.getProjectMonthProgressList();
this.$message("洗掉成功~");
this.getProject();
}
})
}).catch(() => {
this.$message("取消洗掉~");
})
}
}
};
</script>
<style lang="scss" scoped="scoped">
.box-main2{
width:1100px;
margin:20px auto;
background: #fff;
.detail{
padding: 20px;
width:900px;
margin:0 auto;
span{
padding: 10px;
}
}
.box-table, .box-page1{
margin-top:20px;
}
}
</style>
添加路由
index.js
import Vue from 'vue';
import Router from 'vue-router';
import Frame from '@/views/layout/Frame';
Vue.use(Router);
export default new Router({
routes: [
{
path: '/',
component: Frame,
children: [
{
path: '/project-list',
meta: {pageTitle: '專案頁', leftMenuIndex: 'project-list'},
component: () => import('@/views/ProjectList')
},
{
path: '/project-detail',
meta: {pageTitle: '專案詳情頁', leftMenuIndex: 'project-detail'},
component: () => import('@/views/ProjectDetail')
},
{
path: '/project-month-progress',
meta: {pageTitle: '專案月份進度頁', leftMenuIndex: 'project-month-progress'},
component: () => import('@/views/ProjectMonthProgress')
},
]
},
]
});
添加左側選單顯示
LeftMenu.vue
<el-menu-item index="project-list" @click.native="clkItem('/project-list')">
<i class="menuitem-icon iconfont icon-logging"></i>
<span class="menuitem-text" slot="title">專案串列</span>
</el-menu-item>
后端原始碼
API
ProjectController專案訪問類
package com.wanshi.controller;
import com.github.pagehelper.PageInfo;
import com.wanshi.bean.Project;
import com.wanshi.bean.ResultBean;
import com.wanshi.service.ProjectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@CrossOrigin
@RequestMapping("/project")
public class ProjectController {
@Autowired
private ProjectService projectService;
@PostMapping("/page")
public ResultBean<PageInfo<Project>> page(@RequestBody Project param) {
ResultBean<PageInfo<Project>> res = projectService.page(param);
return res;
}
@PostMapping("/save")
public ResultBean<Integer> save(@RequestBody Project param) {
ResultBean<Integer> res = projectService.save(param);
return res;
}
@PostMapping("/delete")
public ResultBean<Integer> delete(@RequestBody Project param) {
ResultBean<Integer> res = projectService.delete(param);
return res;
}
@PostMapping("/get")
public ResultBean<Project> get(@RequestBody Project param) {
ResultBean<Project> res = projectService.get(param);
return res;
}
}
ProjectMonthProgressController 專案月份進度訪問類
package com.wanshi.controller;
import com.github.pagehelper.PageInfo;
import com.wanshi.bean.ProjectMonthProgress;
import com.wanshi.bean.ResultBean;
import com.wanshi.service.ProjectMonthProgressService;
import org.junit.experimental.theories.DataPoints;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@CrossOrigin
@RequestMapping("/project_month_progress")
public class ProjectMonthProgressController {
@Autowired
private ProjectMonthProgressService projectMonthProgressService;
@PostMapping("/page")
public ResultBean<PageInfo<ProjectMonthProgress>> page(@RequestBody ProjectMonthProgress param) {
ResultBean<PageInfo<ProjectMonthProgress>> res = projectMonthProgressService.page(param);
return res;
}
@PostMapping("/save")
public ResultBean<Integer> save(@RequestBody ProjectMonthProgress param) {
ResultBean<Integer> res = projectMonthProgressService.save(param);
return res;
}
@PostMapping("/delete")
public ResultBean<Integer> delete(@RequestBody ProjectMonthProgress param) {
ResultBean<Integer> res = projectMonthProgressService.delete(param);
return res;
}
}
ProvinceController省份訪問類
package com.wanshi.controller;
import com.wanshi.bean.Province;
import com.wanshi.bean.ResultBean;
import com.wanshi.service.ProvinceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@CrossOrigin
@RequestMapping("/province")
public class ProvinceController {
@Autowired
private ProvinceService provinceService;
@PostMapping("/list")
public ResultBean<List<Province>> list() {
ResultBean<List<Province>> res = provinceService.list();
return res;
}
}
Service
ProjectService類
package com.wanshi.service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wanshi.bean.Project;
import com.wanshi.bean.ProjectMonthProgress;
import com.wanshi.bean.Province;
import com.wanshi.bean.ResultBean;
import com.wanshi.mapper.ProjectMapper;
import com.wanshi.mapper.ProjectMonthProgressMapper;
import com.wanshi.mapper.ProvinceMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@Service
public class ProjectService {
@Autowired
private ProjectMapper projectMapper;
@Autowired
private ProvinceMapper provinceMapper;
@Autowired
private ProjectMonthProgressMapper projectMonthProgressMapper;
public ResultBean<PageInfo<Project>> page(Project param) {
PageHelper.startPage(param.getPageNum(), param.getPageSize());
List<Project> projectList = projectMapper.list(param);
for (Project project : projectList) {
if (project != null) {
//回顯省份名稱
Province province = new Province();
province.setNoid(project.getProvince_id());
Province province1 = provinceMapper.get(province);
project.setStr_province(province1.getProvince_name());
//獲取進度記錄
ProjectMonthProgress projectMonthProgress = new ProjectMonthProgress();
projectMonthProgress.setProject_id(project.getNoid());
List<ProjectMonthProgress> projectMonthProgressList = projectMonthProgressMapper.list(projectMonthProgress);
if (projectMonthProgressList != null) {
Double done_money = 0.0;
for (ProjectMonthProgress monthProgress : projectMonthProgressList) {
if (monthProgress != null && monthProgress.getProject_id() == project.getNoid()) {
done_money += monthProgress.getProgress_money();
}
}
project.setDone_money(done_money);
project.setIncomplete_money(project.getContract_money() - done_money);
}
}
}
PageInfo<Project> pageInfo = new PageInfo<>(projectList);
return ResultBean.create(0, "success", pageInfo);
}
public ResultBean<Integer> save(Project param) {
if (param.getNoid() != null) {
projectMapper.update(param);
} else {
projectMapper.insert(param);
}
return ResultBean.create(0, "success", null);
}
public ResultBean<Integer> delete(Project param) {
projectMapper.delete(param);
return ResultBean.create(0, "success", null);
}
public ResultBean<Project> get(Project param) {
Project project = projectMapper.get(param);
//回顯省份名稱
Province province = new Province();
province.setNoid(project.getProvince_id());
Province province1 = provinceMapper.get(province);
project.setStr_province(province1.getProvince_name());
//獲取進度記錄
ProjectMonthProgress projectMonthProgress = new ProjectMonthProgress();
projectMonthProgress.setProject_id(project.getNoid());
List<ProjectMonthProgress> projectMonthProgressList = projectMonthProgressMapper.list(projectMonthProgress);
Double done_money = 0.0;
for (ProjectMonthProgress monthProgress : projectMonthProgressList) {
if (monthProgress != null) {
done_money += monthProgress.getProgress_money();
}
}
project.setDone_money(done_money);
project.setIncomplete_money(project.getContract_money() - done_money);
return ResultBean.create(0, "success", project);
}
}
ProjectMonthProgressService類
package com.wanshi.service;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wanshi.bean.ProjectMonthProgress;
import com.wanshi.bean.ResultBean;
import com.wanshi.mapper.ProjectMonthProgressMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class ProjectMonthProgressService {
@Autowired
private ProjectMonthProgressMapper projectMonthProgressMapper;
public ResultBean<PageInfo<ProjectMonthProgress>> page(ProjectMonthProgress param) {
PageHelper.startPage(param.getPageNum(), param.getPageSize());
List<ProjectMonthProgress> projectMonthProgressList = projectMonthProgressMapper.list(param);
for (ProjectMonthProgress projectMonthProgress : projectMonthProgressList) {
if (projectMonthProgress != null) {
String progress_time = projectMonthProgress.getProgress_year()+"-"+projectMonthProgress.getProgress_month();
projectMonthProgress.setProgress_time(progress_time);
}
}
PageInfo<ProjectMonthProgress> pageInfo = new PageInfo<>(projectMonthProgressList);
return ResultBean.create(0, "success", pageInfo);
}
public ResultBean<Integer> save(ProjectMonthProgress param) {
if (!StringUtils.isEmpty(param.getProgress_time())) {
param.setProgress_year(Integer.valueOf(param.getProgress_time().substring(0, 4)));
param.setProgress_month(Integer.valueOf(param.getProgress_time().substring(5)));
}
if (param.getNoid() != null) {
projectMonthProgressMapper.update(param);
} else {
projectMonthProgressMapper.insert(param);
}
return ResultBean.create(0, "success", null);
}
public ResultBean<Integer> delete(ProjectMonthProgress param) {
projectMonthProgressMapper.delete(param);
return ResultBean.create(0, "success", null);
}
}
代碼過于多,就不一一展示了,文末我會提供下載源代碼鏈接哦~
下載鏈接
本專案上傳至GitEE碼云進行專案管理,具體鏈接如下:
前端原始碼:建筑工程專案前端原始碼
后端原始碼:建筑工程專案后端原始碼
建議使用SSH秘鑰爬取原始碼
前端配置教程:使用GitEE拉取前端專案并配置,保證運行成功哦~
💝💝💝
博主寄語
該專案是一個基于SpringBoot + Vue實作的建筑專案進度管理系統,專案邏輯稍微復雜,但只要你細心,堅持的敲上幾遍,相信你的編程能力會極大的提升,加油~
若在本專案中遇到技術難題,可在下方評論區留言或私信我,授人以魚不如授人以漁
如果你覺得博主寫的不錯的話,不妨給個一鍵三連,點擊下方小拳頭即可一鍵三連,
💝💝💝

轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/413471.html
標籤:其他
上一篇:閉包和this指向問題
下一篇:Border of CSS3
