Explorar o código

工时管家——项目管理修改

ZhouRuiTing %!s(int64=5) %!d(string=hai) anos
pai
achega
7cc142f1da

+ 4 - 1
fhKeeper/formulahousekeeper/timesheet/src/port.js

@@ -36,8 +36,11 @@ export default {
         listPage: '/project/getProjectPage',                    // 获取项目列表分页
         delete: '/project/deleteProject',                       // 删除项目
         add: '/project/editProject',                            // 新增项目
-        listCost: '/project/getTimeCost',                       // 获取所有项目花费的工时
+
+        listCost: '/project/getTimeCost',                       // 获取每个项目花费的工时
+        depCost: '/department/departmentStatistic',             // 获取每个部门花费的工时
         projectCost: '/project/getProjectCost',                 // 获取某个项目每个人分别花费的工时
+        userCost: '/department/userStatistic',                  // 获取当前部门每个人分别花费的工时
     },
 
     //日报

+ 4 - 2
fhKeeper/formulahousekeeper/timesheet/src/routes.js

@@ -15,8 +15,9 @@ import daily from './views/workReport/daily.vue'
 
 // 项目管理
 import list from './views/project/list.vue'
-import proDetail from './views/project/detail.vue'
 import cost from './views/project/cost.vue'
+import proDetail from './views/project/detail.vue'
+import depDetail from './views/project/detailDep.vue'
 
 // 团队管理
 import team from './views/team/index.vue'
@@ -69,7 +70,8 @@ let routes = [
         children: [
             { path: '/list', component: list, name: '项目列表' },
             { path: '/cost', component: cost, name: '成本统计' },
-            { path: '/cost/:id/:name', component: proDetail, name: '项目详情', hidden: true },
+            { path: '/cost/:id/:name', component: proDetail, name: '成本详情', hidden: true },
+            { path: '/costDep/:id/:name', component: depDetail, name: '成本详情', hidden: true },
         ]
     },
     //组织架构

+ 54 - 16
fhKeeper/formulahousekeeper/timesheet/src/views/project/cost.vue

@@ -1,5 +1,13 @@
 <template>
-    <div id="container"></div> 
+    <section>
+        <el-col :span="24" style="padding-bottom: 0px;text-align:center;">
+            <el-radio-group v-model="radio" @change="getEchart">
+                <el-radio-button label="项目"></el-radio-button>
+                <el-radio-button label="部门"></el-radio-button>
+            </el-radio-group>
+        </el-col>
+        <div id="container" :style="'height:'+containerHeight+'px'"></div>
+    </section>
 </template>
 
 <script>
@@ -8,24 +16,37 @@
         data() {
             return {
                 user: JSON.parse(sessionStorage.getItem("user")),
-
-                myChart: null
+                radio: sessionStorage.radio!=null?sessionStorage.radio:'项目',
+                containerHeight: 0,    
+                myChart: null,
+                params: null,
             };
         },
         methods: {
             getEchart(){
+                sessionStorage.radio = this.radio;
                 var _this = this;
-                this.http.post(this.port.project.listCost, {},
+                this.http.post(this.radio=='项目'?this.port.project.listCost:this.port.project.depCost, {},
                 res => {
                     if (res.code == "ok") {
-                        var xList = [], yList = [], list = res.data.costList, totalMoneyCost = res.data.totalMoneyCost;
+                        var xList = [], yList = [], list = res.data.costList, 
+                        totalMoneyCost = (this.radio=='项目'?res.data.totalMoneyCost:res.data.totalCostMoney);
                         for(var i in list) {
-                            xList.push(list[i].project);
-                            yList.push({
-                                "value": list[i].cost,
-                                "id": list[i].id,
-                                "cost": list[i].costMoney
-                            });
+                            if(this.radio=='项目') {
+                                xList.push(list[i].project);
+                                yList.push({
+                                    "value": list[i].cost,
+                                    "id": list[i].id,
+                                    "cost": list[i].costMoney
+                                });
+                            } else {
+                                xList.push(list[i].departmentName);
+                                yList.push({
+                                    "value": list[i].costTime,
+                                    "id": list[i].departmentId,
+                                    "cost": list[i].costMoney
+                                });
+                            }
                         }
 
                         var myChart = echarts.init(document.getElementById("container"));
@@ -61,6 +82,7 @@
                                 formatter: function (params,ticket,callback) {
                                     var res = params[0].name + "<br/>工作时长(h)"+" : " + params[0].data.value 
                                     + "h <br/>工作成本(元)"+" : " + params[0].data.cost + "元";
+                                    _this.params = params;
                                     return res;
                                 }
                             },
@@ -84,8 +106,23 @@
                             }]
                         };
                         myChart.setOption(option);
-                        myChart.on('click', function(params) {
-                            _this.$router.push("/cost/" + params.data.id + "/" + params.name);
+                        // myChart.on('click', function(params) {
+                        //     if(_this.radio=='项目') {
+                        //         _this.$router.push("/cost/" + params.data.id + "/" + params.name);
+                        //     } else {
+                        //         _this.$router.push("/costDep/" + params.data.id + "/" + params.name);
+                        //     }
+                        // });
+                        myChart.getZr().on('click', params => {
+                            const pointInPixel = [params.offsetX, params.offsetY];
+                            if (myChart.containPixel('grid', pointInPixel)) {
+                                console.log(_this.params)
+                                if(_this.radio=='项目') {
+                                    _this.$router.push("/cost/" + _this.params[0].data.id + "/" + _this.params[0].name);
+                                } else {
+                                    _this.$router.push("/costDep/" + _this.params[0].data.id + "/" + _this.params[0].name);
+                                }
+                            }
                         });
                     } else {
                         this.$message({
@@ -100,15 +137,15 @@
                         type: "error"
                     });
                 });
-            }
+            },
         },
         created() {
         },
         mounted() {
-            this.$el.style.height = (window.innerHeight - 100) + "px";
+            this.containerHeight = window.innerHeight - 140
             const that = this;
             window.onresize = function temp() {
-                that.$el.style.height = (window.innerHeight - 100) + "px";
+                this.containerHeight = window.innerHeight - 100
             };
             this.getEchart();
             var _this = this;
@@ -121,6 +158,7 @@
 
 <style lang="scss" scoped>
     #container {
+        display: inline-block;
         width: 100%; 
         margin-top: 10px;
     }  

+ 286 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/project/detailDep.vue

@@ -0,0 +1,286 @@
+<template>
+    <section>
+        <!--工具条-->
+        <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
+            <el-form :inline="true">
+                <el-form-item>
+                    <el-button type="text" @click="backToList" icon="el-icon-back" class="back">返回</el-button>
+                </el-form-item>
+                <el-form-item class="divLine"></el-form-item>
+                <el-form-item>
+                    <span class="workName">{{detailName}}</span>
+                    <el-cascader v-model="departmentId" placeholder="请选择部门" style="width: 70%;margin-left:10px;" @change="getList"
+                    :options="option" :props="{ checkStrictly: true }" :show-all-levels="false"></el-cascader>
+                </el-form-item>
+                <el-form-item style="float:right;">
+                    <span style="font-size:18px;">部门成本:<span style="color:#20a0ff;">{{cost}}元</span></span>
+                </el-form-item>
+            </el-form>
+        </el-col>
+
+        <div id="container" :style="'height:' + tableHeight + 'px'"></div> 
+    </section>
+</template>
+
+<script>
+    import util from "../../common/js/util";
+
+    export default {
+        data() {
+            return {
+                detailId: this.$route.params.id,
+                detailName: this.$route.params.name,
+
+                user: JSON.parse(sessionStorage.getItem("user")),
+
+                cost: 0,
+
+                tableHeight: 0,
+                
+                echart: null,
+
+                option: [],
+                departmentId: [].concat(parseInt(this.$route.params.id)),
+            };
+        },
+        methods: {
+            //返回
+            backToList() {
+                this.$router.go(-1);
+            },
+
+            // 获取部门列表
+            getDepartment() {
+                this.http.post( this.port.manage.depList, {},
+                res => {
+                    if (res.code == "ok") {
+                        var list = res.data , array = [];
+                        for(var i in list) {
+                            if(list[i].id == this.detailId) {
+                                array.push(list[i])
+                            }
+                        }
+                        this.option = this.changeArr(array);
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+
+            // 修改数组
+            changeArr(arr) {
+                for (var i = 0; i < arr.length; i++) {
+                    if(arr[i].id != -1 && arr[i].id != 0) {
+                        if (arr[i].children != null && arr[i].children.length>0) {
+                            arr[i].children = this.changeArr(arr[i].children);
+                        }
+                        arr[i].id && (arr[i].value = arr[i].id);
+                        delete arr[i].id;
+                    }
+                }
+                for(var i in arr) {
+                    if(arr[i].id == -1 || arr[i].id == 0) {
+                        arr.splice(i,1)
+                    }    
+                }
+                return arr;
+            },
+
+            //获取项目列表
+            getList() {
+                this.listLoading = true;
+                this.http.post(this.port.project.userCost, {
+                    departmentId: this.departmentId[this.departmentId.length-1],
+                },
+                res => {
+                    this.listLoading = false;
+                    var _this = this;
+                    if (res.code == "ok") {
+                        var xList = [] , yList = [] , list = res.data , array = [] , series = [];
+                        this.cost = res.data.totalMoneyCost;
+                        var num = list[0].project.length;
+                        for(var i in list) {
+                            xList.push(list[i].name);
+                            var pro = list[i].project;
+                            for(var j in pro) {
+                                if(array.indexOf(pro[j].project) == -1) {
+                                    array.push(pro[j].project)
+                                }
+                            }
+                        }
+
+                        for(var i in array) {
+                            yList.push(array[i]);
+                            var dataList = [];
+                            for(var j in list) {
+                                var project = list[j].project , num = 0;
+                                if(project.length != 0) {
+                                    for(var k in project) {
+                                        if(project[k].project == array[i]) {
+                                            dataList.push({
+                                                "value": project[k].time,
+                                                "cost": project[k].money,
+                                            })
+                                        } else {
+                                            num++;
+                                        }
+                                        if(k == project.length-1 && num != project.length-1) {
+                                            dataList.push({
+                                                "value": 0,
+                                                "cost": 0,
+                                            })
+                                        }
+                                    }
+                                } else {
+                                    dataList.push({
+                                        "value": 0,
+                                        "cost": 0,
+                                    })
+                                }
+                            }
+                            series.push({
+                                name: array[i],
+                                type: 'bar',
+                                stack:'1',
+                                barMaxWidth: 30,
+                                data: dataList,
+                            })
+                        }
+
+                        var myChart = echarts.init(document.getElementById("container"));
+                        _this.myChart = myChart;
+                        var option = {
+                            // 工具箱
+                            legend: {
+                                x: 80,
+                                y: 10,
+                                data: yList
+                            },
+                            grid : {
+                                top : 80,    //距离容器上边界40像素
+                                bottom: 35   //距离容器下边界30像素
+                            },
+                            toolbox: {
+                                show: true,
+                                feature:{
+                                    saveAsImage:{
+                                        show:true
+                                    },
+                                    restore:{
+                                        show:true
+                                    },
+                                    dataView:{
+                                        show:true
+                                    },
+                                    dataZoom:{
+                                        show:true
+                                    },
+                                    magicType:{
+                                        type:['line','bar']
+                                    }
+                                }
+                            },
+                            tooltip:{
+                                trigger:'axis',
+                                formatter: function (params,ticket,callback) {
+                                    var res = params[0].name + "<br/>";
+                                    for(var i in params) {
+                                        res += "项目名称:" + params[i].seriesName 
+                                        + "<br/>工作时长(h)" + params[i].data.value
+                                        + "h <br/>工作成本(元)"+" : " + params[i].data.cost + "元</br></br>";
+                                    }
+                                    return res;
+                                }
+                            },
+                            xAxis: {
+                                data: xList,
+                                axisLabel: {
+                                    interval:0,rotate:20
+                                }
+                            },
+                            yAxis: [{
+                                type : 'value',
+                                axisLabel: {
+                                    formatter:'{value} (h)'
+                                }
+                            }],
+                            series: series,
+                        };
+                        myChart.setOption(option);
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.listLoading = false;
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+        },
+        created() {
+            let height = window.innerHeight;
+            this.tableHeight = height - 145;
+            const that = this;
+            window.onresize = function temp() {
+                that.tableHeight = window.innerHeight - 145;
+            };
+        },
+        mounted() {
+            this.getDepartment();
+            this.getList();
+            var _this = this;
+            window.addEventListener("resize", function() {
+                _this.myChart.resize();
+            });
+        }
+    };
+</script>
+
+<style lang="scss" scoped>
+    .toolbar {
+        .el-form-item {
+            font-size: 14px;
+            vertical-align: middle;
+        }
+        .back {
+            font-size: 16px;
+            cursor: pointer;
+        }
+        .divLine {
+            width: 2px;
+            background: #c3c3c3;
+            height: 100%;
+        }
+        .workName {
+            color: #333;
+            font-size: 18px;
+        }
+        .workHours {
+            color: #20a0ff;
+            font-size: 18px;
+        }
+    }
+
+    #container {
+        float: left;
+        width: 100%;
+    }
+</style>
+
+<style lang="scss">
+</style>

+ 67 - 6
fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue

@@ -1,6 +1,6 @@
 <template>
     <section>
-    <!--工具条-->
+        <!--工具条-->
         <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
             <el-form :inline="true">
                 <el-form-item style="float:right;">
@@ -13,6 +13,7 @@
         <el-table :data="list" highlight-current-row v-loading="listLoading" :height="tableHeight" style="width: 100%;">
             <el-table-column type="index" width="60"></el-table-column>
             <el-table-column prop="projectName" label="项目名称" sortable></el-table-column>
+            <el-table-column prop="userNames" label="参与者" sortable></el-table-column>
             <el-table-column label="操作" width="220">
                 <template slot-scope="scope">
                     <!-- <el-button size="small" type="primary" @click="detail(scope.$index)">详情</el-button> -->
@@ -36,11 +37,16 @@
         </el-col>
 
         <!--新增界面-->
-        <el-dialog :title="title" v-if="addFormVisible" :visible.sync="addFormVisible" :close-on-click-modal="false" customClass="customWidth">
+        <el-dialog :title="title" v-if="addFormVisible" :visible.sync="addFormVisible" :close-on-click-modal="false" customClass="customWidth" width="600px">
             <el-form ref="form1" :model="addForm" :rules="rules" label-width="100px">
                 <el-form-item label="项目名称" prop="name">
                     <el-input v-model="addForm.name" placeholder="请输入项目名称" clearable></el-input>
                 </el-form-item>
+                <el-form-item label="参与者">
+                    <el-select v-model="addForm.userId" multiple filterable placeholder="请选择参与者" style="width:100%;">
+                        <el-option v-for="item in users" :key="item.id" :label="item.name" :value="item.id"></el-option>
+                    </el-select>
+                </el-form-item>
             </el-form>
             <div slot="footer" class="dialog-footer">
                 <el-button @click.native="addFormVisible = false">取消</el-button>
@@ -59,6 +65,7 @@
                 user: JSON.parse(sessionStorage.getItem("user")),
 
                 date: new Date(),
+                users: [],
 
                 tableHeight: 0,
                 listLoading: false,
@@ -72,6 +79,7 @@
                 title: "",
                 addForm: {
                     name: '',
+                    userId: [],
                 },
                 rules: {
                     name: [{ required: true, message: "请输入项目名称", trigger: "blur" }],
@@ -79,6 +87,30 @@
             };
         },
         methods: {
+            getUsers() {
+                this.http.post(this.port.manage.list, {
+                    departmentId: -1,
+                    pageIndex: 1,
+                    pageSize: 99999
+                },
+                res => {
+                    if (res.code == "ok") {
+                        this.users = res.data.records;
+                    } else {
+                        this.$message({
+                        message: res.msg,
+                        type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+
             //分页
             handleCurrentChange(val) {
                 this.page = val;
@@ -100,7 +132,19 @@
                 res => {
                     this.listLoading = false;
                     if (res.code == "ok") {
-                        this.list = res.data.records;
+                        var list = res.data.records;
+                        for(var i in list) {
+                            var participator = list[i].participator , str = "";
+                            for(var j in participator) {
+                                if(j == participator.length-1) {
+                                    str += participator[j].name
+                                } else {
+                                    str += participator[j].name + ','
+                                }
+                            }
+                            list[i].userNames = str;
+                        }
+                        this.list = list;
                         this.total = res.data.total;
                     } else {
                         this.$message({
@@ -123,13 +167,19 @@
                 if(i == -1) {
                     this.title = "新增项目";
                     this.addForm = {
-                        name: ''
+                        name: '',
+                        userId: [],
                     }
                 } else {
                     this.title = "修改项目";
+                    var list = this.list[i].participator , arr = [];
+                    for(var j in list) {
+                        arr.push(list[j].id)
+                    }
                     this.addForm = {
                         id: this.list[i].id,
-                        name: this.list[i].projectName
+                        name: this.list[i].projectName,
+                        userId: arr
                     }
                 }
                 this.addFormVisible = true;
@@ -139,7 +189,17 @@
                 this.$refs.form1.validate(valid => {
                     if (valid) {
                         this.addLoading = true;
-                        this.http.post(this.port.project.add,this.addForm,
+                        let formData = new FormData();
+                        formData.append("name", this.addForm.name);
+                        if(this.addForm.id != null) {
+                            formData.append("id", this.addForm.id);
+                        }
+                        if(this.addForm.userId.length != 0) {
+                            for(var j in this.addForm.userId) {
+                                formData.append("userId", this.addForm.userId[j]);
+                            }
+                        }
+                        this.http.uploadFile(this.port.project.add,formData,
                         res => {
                             this.addLoading = false;
                             if (res.code == "ok") {
@@ -220,6 +280,7 @@
         },
         mounted() {
             this.getList();
+            this.getUsers();
         }
     };
 </script>