|
@@ -41,6 +41,8 @@
|
|
|
<el-menu-item index="1-19" v-if="user.timeType.restartTaskNeedReason == 1" @click="ssl(18)"><p>任务重启表</p></el-menu-item>
|
|
|
<el-menu-item index="1-20" v-if="permissions.reportFTEAll || permissions.reportFTEPart" @click="ssl(19)"><p>FTE报表</p></el-menu-item>
|
|
|
<el-menu-item index="1-21" v-if="permissions.reportEfficent" @click="ssl(20)"><p>有效工时率表</p></el-menu-item>
|
|
|
+ <el-menu-item index="1-22" @click="ssl(21)"><p>项目分类工时占比表</p></el-menu-item>
|
|
|
+ <el-menu-item index="1-23" @click="ssl(22)" v-if="false"><p>分类工时明细表</p></el-menu-item>
|
|
|
<!-- <el-menu-item index="1-12"><p @click="ssl(11)">人员工时统计表</p></el-menu-item> -->
|
|
|
</el-submenu>
|
|
|
</el-menu>
|
|
@@ -74,14 +76,23 @@
|
|
|
</el-select>
|
|
|
</template>
|
|
|
<!-- 时间段筛选 -->
|
|
|
- <template v-if="ins == 6 || ins == 8 || ins == 9 || ins == 10 || ins == 11 || ins == 12 || ins == 5 || ins == 16 || ins == 17 || ins == 18 || ins == 20">
|
|
|
- <span>
|
|
|
- <span class="demonstration" style="color:#999;padding:0 10px">
|
|
|
- {{ ins == 15 ? $t('xiang-mu-chuang-jian-shi-jian-duan') : $t('message.period') }}
|
|
|
- </span>
|
|
|
- <el-date-picker v-model="rangeDatas" type="daterange" value-format="yyyy-MM-dd" :placeholder="$t('selectstartdate')" @change="picks()" :range-separator="$t('other.to')" :start-placeholder="$t('time.startDate')" :end-placeholder="$t('time.endDate')" style="width:300px" :clearable="ins == 15" size="small"> </el-date-picker>
|
|
|
+ <template v-if="ins == 6 || ins == 8 || ins == 9 || ins == 10 || ins == 11 || ins == 12 || ins == 5 || ins == 16 || ins == 17 || ins == 18 || ins == 20 || ins == 21">
|
|
|
+ <span>
|
|
|
+ <span class="demonstration" style="color:#999;padding:0 10px">
|
|
|
+ {{ ins == 15 ? $t('xiang-mu-chuang-jian-shi-jian-duan') : $t('message.period') }}
|
|
|
</span>
|
|
|
- </template>
|
|
|
+ <el-date-picker v-model="rangeDatas" type="daterange" value-format="yyyy-MM-dd" :placeholder="$t('selectstartdate')" @change="picks()" :range-separator="$t('other.to')" :start-placeholder="$t('time.startDate')" :end-placeholder="$t('time.endDate')" style="width:300px" :clearable="ins == 15" size="small"> </el-date-picker>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ <!-- 日期筛选 -->
|
|
|
+ <template v-if="ins == 22">
|
|
|
+ <span>
|
|
|
+ <span class="demonstration" style="color:#999;padding:0 10px">
|
|
|
+ 日期
|
|
|
+ </span>
|
|
|
+ <el-date-picker v-model="dateSelect" size="small" type="date" placeholder="选择日期" value-format="yyyy-MM-dd" @change="picks()"></el-date-picker>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
|
|
|
<!-- 按部门/项目筛选 -->
|
|
|
<!-- <el-select v-if="ins == 10" v-model="departmentOrProject" placeholder="请选择" size="small" @change="selcts(10)" style="margin-left:10px;width:120px">
|
|
@@ -89,7 +100,7 @@
|
|
|
<el-option label="查看部门审核人" :value="0"></el-option>
|
|
|
</el-select> -->
|
|
|
<!-- 项目筛选 -->
|
|
|
- <el-select v-if="ins != 4 && ins != 8 && ins != 9 && ins != 19 && ins != 10 && ins != 11 && ins != 14 && ins != 15 && ins != 17 && ins != 20" v-model="proJuctId" :placeholder="$t('defaultText.pleaseSelectSnItem')" clearable filterable size="small" @change="selcts()" style="margin-left:10px">
|
|
|
+ <el-select v-if="ins != 4 && ins != 8 && ins != 9 && ins != 19 && ins != 10 && ins != 11 && ins != 14 && ins != 15 && ins != 17 && ins != 20 && ins != 21 && ins != 22" v-model="proJuctId" :placeholder="$t('defaultText.pleaseSelectSnItem')" clearable filterable size="small" @change="selcts()" style="margin-left:10px">
|
|
|
<el-option v-for="(item) in proListOvertime" :key="item.id" :label="item.projectName + (item.projectCode ? item.projectCode : '')" :value="item.id">
|
|
|
<span style="float: left;color: #8492a6;">{{ item.projectCode }}</span>
|
|
|
<span style="float: right;font-size: 13px;margin-left: 20px">{{ item.projectName }}</span>
|
|
@@ -152,9 +163,10 @@
|
|
|
</div>
|
|
|
<!-- <p :style="ins == 9 ? 'float: right;margin-right: 25px;width:20%' : 'float: right;margin-right: 25px;width:10%'" > -->
|
|
|
<p :style="`${ins == 9 ? 'width:20%' : ins == 14 ? 'width: 20%' : 'width: 10%'}`" class="tableRightBtn">
|
|
|
- <el-button type="primary" @click="exportExcel" size="mini">{{ $t('reporderived') }}</el-button>
|
|
|
+ <el-button type="primary" @click="exportExcel" size="mini" v-if="ins != 21 && ins != 22">{{ $t('reporderived') }}</el-button>
|
|
|
<el-button type="primary" @click="fillAll" size="mini" v-if="ins == 14">全部补足</el-button>
|
|
|
<el-button type="primary" @click="exportExcelByQuarter" size="mini" v-if="ins == 9 && user.companyId == 876">{{ $t('an-ji-du-dao-chu') }}</el-button>
|
|
|
+ <el-button type="primary" @click="setWarning" size="mini" v-if="ins == 21">设置预警</el-button>
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
@@ -925,8 +937,53 @@
|
|
|
</el-table-column>
|
|
|
<el-table-column align="center" prop="rate" label="有效工时率" min-width="150"></el-table-column>
|
|
|
</el-table>
|
|
|
+
|
|
|
+ <!-- 项目分类工时占比表 -->
|
|
|
+ <el-table v-if="ins == 21" :key="projectCateRatioListKey" border :data="projectCateRatioList.userList" highlight-current-row v-loading="listLoading" :height="(+tableHeight + 50) - 1" style="width: 100%;" >
|
|
|
+ <el-table-column align="center" prop="name" label="人员" min-width="150" fixed="left">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div>
|
|
|
+ <span v-if="user.userNameNeedTranslate == '1'">
|
|
|
+ <ww-open-data type='userName' :openid='scope.row.userName'></ww-open-data>
|
|
|
+ </span>
|
|
|
+ <span v-if="user.userNameNeedTranslate != '1'">
|
|
|
+ {{scope.row.userName}}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column align="center" prop="workingTime" label="总工时" min-width="150">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ {{ scope.row.workingTime }} h
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column align="center" prop="s" :label="item.name" min-width="150" v-for="item in projectCateRatioList.categoryList" :key="item.id">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <div v-for="v,i in scope.row.cateTimeList || []" :key="i">
|
|
|
+ <div v-if="item.name == v.categoryName && v.categoryName" :style="`color: ${v.warning ? 'red' : ''}`">
|
|
|
+ <div>工时: {{ v.workingTime }} h </div>
|
|
|
+ <div>占比: {{ v.percent | schedulePercentage }} % </div>
|
|
|
+ </div>
|
|
|
+ <div v-if="!v.categoryName && item.name == '未分类'" :style="`color: ${v.warning ? 'red' : ''}`">
|
|
|
+ <div>工时: {{ v.workingTime }} h </div>
|
|
|
+ <div>占比: {{ v.percent | schedulePercentage }} % </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <!-- 分类工时明细表 -->
|
|
|
+ <el-table v-if="ins == 22" key="22" border :data="hoursDetailClassList" highlight-current-row v-loading="listLoading" :height="tableHeight + 50" style="width: 100%;" >
|
|
|
+ <el-table-column align="center" prop="c" label="姓名" min-width="150"></el-table-column>
|
|
|
+ <el-table-column align="center" prop="x" label="部门" min-width="150"></el-table-column>
|
|
|
+ <el-table-column align="center" prop="p" label="人员类型" min-width="150"></el-table-column>
|
|
|
+ <el-table-column align="center" prop="j" label="生产工时" min-width="150"></el-table-column>
|
|
|
+ <el-table-column align="center" prop="workingTime" label="总工时" min-width="150"></el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
<!--工具条-->
|
|
|
- <el-col :span="24" class="toolbar" v-if="ins != 6 && ins != 20">
|
|
|
+ <el-col :span="24" class="toolbar" v-if="ins != 6 && ins != 20 && ins != 21 && ins != 22">
|
|
|
<el-pagination
|
|
|
v-if="ins == 12"
|
|
|
@size-change="groupSizeChange"
|
|
@@ -1139,6 +1196,33 @@
|
|
|
<el-button @click.native="quarterExport" :loading="exportLoading" type="primary">{{ $t('export.export') }}</el-button>
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
+
|
|
|
+ <!-- 设置预警弹窗 -->
|
|
|
+ <el-dialog title="设置预警" :visible.sync="setWarningModal" width="600px" :before-close="handleClose">
|
|
|
+ <div>
|
|
|
+ <el-form ref="warningFrom" :model="warningFrom" label-width="120px">
|
|
|
+ <el-form-item label="提醒分类:">
|
|
|
+ <el-select v-model="warningFrom.monitorCategoryId" placeholder="请选择提醒分类">
|
|
|
+ <el-option v-for="item in projectCateRatioList.categoryList" :key="item.id" :label="item. name" :value="item.id"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="选择关系:">
|
|
|
+ <el-radio v-model="warningFrom.moreOrLess" :label="0">低于</el-radio>
|
|
|
+ <el-radio v-model="warningFrom.moreOrLess" :label="1">高于</el-radio>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="设置占比:">
|
|
|
+ <div class="sliderSetup">
|
|
|
+ <el-slider v-model="warningFrom.ratio" style="width: 340px"></el-slider>
|
|
|
+ <div class="text">{{ warningFrom.ratio }} %</div>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ <span slot="footer" class="dialog-footer">
|
|
|
+ <el-button @click="setWarningModal = false">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="setForewarning()" :loading="warningTableLoading">确 定</el-button>
|
|
|
+ </span>
|
|
|
+ </el-dialog>
|
|
|
</section>
|
|
|
</template>
|
|
|
|
|
@@ -1212,13 +1296,13 @@ export default {
|
|
|
this.$t('pojectbalancesheetincomestatement'),this.$t('customerprojectprofitstatement'),this.$t('projectphasetimesheet'),
|
|
|
this.$t('statisticsofovertimework'),this.$t('timecostearlywarningtable'),this.$t('personneltimeallocationtable'),
|
|
|
this.$t('statisticsofstafffillingintimerate'),this.$t('dailyreporttobereviewedstatistics'),this.$t('statisticsofpersonnelhours'),this.$t('taskgrouptimesheet'),this.$t('projectcostbaselinetable'),
|
|
|
- this.$t('ren-yuan-yue-du-gong-shi-biao'), this.$t('bumenchanyuqingkuang'), this.$t('ge-fen-zu-yu-jie-duan-gong-shi-biao'), '子项目工时成本表', '任务重启表', 'FTE报表', '有效工时率表'],
|
|
|
+ this.$t('ren-yuan-yue-du-gong-shi-biao'), this.$t('bumenchanyuqingkuang'), this.$t('ge-fen-zu-yu-jie-duan-gong-shi-biao'), '子项目工时成本表', '任务重启表', 'FTE报表', '有效工时率表', '项目分类工时占比表', '分类工时明细表'],
|
|
|
|
|
|
shuzArr: [this.$t('projectreport'),this.$t('projectTaskReport'),this.$t('projectcoststatement'),
|
|
|
this.$t('projectbalancesheet'),this.$t('customerprojectincomestatement'),this.$t('projectphasetimesheet'),
|
|
|
this.$t('statisticsofovertimework'),this.$t('timecostearlywarningtable'),this.$t('personneltimeallocationtable'),
|
|
|
this.$t('employeereporttimelinessrate'),this.$t('dailyreporttobereviewedstatistics'),this.$t('statisticsofpersonnelhours'),this.$t('taskgrouptimesheet'),this.$t('projectcostbaselinetable'),
|
|
|
- this.$t('ren-yuan-yue-du-gong-shi-biao'), this.$t('bumenchanyuqingkuang'), this.$t('ge-fen-zu-yu-jie-duan-gong-shi-biao'), '子项目工时成本表', '任务重启表', 'FTE报表','有效工时率表'],
|
|
|
+ this.$t('ren-yuan-yue-du-gong-shi-biao'), this.$t('bumenchanyuqingkuang'), this.$t('ge-fen-zu-yu-jie-duan-gong-shi-biao'), '子项目工时成本表', '任务重启表', 'FTE报表','有效工时率表', '项目分类工时占比表', '分类工时明细表'],
|
|
|
|
|
|
ins: 10000,
|
|
|
user: JSON.parse(sessionStorage.user),
|
|
@@ -1310,8 +1394,22 @@ export default {
|
|
|
label: '服务项目'
|
|
|
}
|
|
|
],
|
|
|
- projectCategorySubId:''
|
|
|
-
|
|
|
+ projectCategorySubId:'',
|
|
|
+
|
|
|
+ projectCateRatioList: {
|
|
|
+ categoryList: [],
|
|
|
+ userList: []
|
|
|
+ }, // 项目分类工时占比表数据
|
|
|
+ setWarningModal: false, // 设置预警弹窗
|
|
|
+ warningTableLoading: false, // 预警表格loading
|
|
|
+ warningFrom: {}, // 预警表单
|
|
|
+ projectCateRatioListKey: 120,
|
|
|
+ forewarningTableList: [{
|
|
|
+ radio: 0,
|
|
|
+ slider: 0,
|
|
|
+ }], // 预警表格数据
|
|
|
+ hoursDetailClassList: [], // 分类工时明细表数据
|
|
|
+ dateSelect: '', // 日期选择
|
|
|
};
|
|
|
},
|
|
|
computed: {},
|
|
@@ -1379,6 +1477,12 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
return str
|
|
|
+ },
|
|
|
+ schedulePercentage(value) {
|
|
|
+ if(!value) {
|
|
|
+ return ''
|
|
|
+ }
|
|
|
+ return value.toFixed(0)
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
@@ -1674,9 +1778,15 @@ export default {
|
|
|
} else if (this.ins == 20) {
|
|
|
this.getEffectiveLaborHourRate();
|
|
|
}
|
|
|
- if(this.ins != 16 && this.ins != 17 && this.ins != 18 && this.ins != 19 && this.ins != 20) {
|
|
|
+ if(this.ins != 16 && this.ins != 17 && this.ins != 18 && this.ins != 19 && this.ins != 20 && this.ins != 21 && this.ins != 22) {
|
|
|
this.getUserList()
|
|
|
}
|
|
|
+ if(this.ins == 21) {
|
|
|
+ this.getProjectWoekScale()
|
|
|
+ }
|
|
|
+ if(this.ins == 22) {
|
|
|
+ this.getHoursDetailClass()
|
|
|
+ }
|
|
|
},
|
|
|
exportExcel() {
|
|
|
var url = "/project";
|
|
@@ -2886,6 +2996,12 @@ export default {
|
|
|
if (this.ins == 20) {
|
|
|
this.getEffectiveLaborHourRate();
|
|
|
}
|
|
|
+ if(this.ins == 21) {
|
|
|
+ this.getProjectWoekScale()
|
|
|
+ }
|
|
|
+ if(this.ins == 22) {
|
|
|
+ this.getHoursDetailClass()
|
|
|
+ }
|
|
|
},
|
|
|
// 任务重启表
|
|
|
taskRestart() {
|
|
@@ -3076,11 +3192,113 @@ export default {
|
|
|
type: 'error'
|
|
|
})
|
|
|
})
|
|
|
- }
|
|
|
+ },
|
|
|
+ // 设置预警
|
|
|
+ setWarning() {
|
|
|
+ this.setWarningModal = true
|
|
|
+ this.getForewarningTableList()
|
|
|
+ },
|
|
|
+ // 单独封装请求
|
|
|
+ async postData(urls, param) {
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ this.http.post(urls, { ...param },
|
|
|
+ res => {
|
|
|
+ if(res.code == 'ok') {
|
|
|
+ resolve(res)
|
|
|
+ } else {
|
|
|
+ this.$message({
|
|
|
+ message: res.msg,
|
|
|
+ type: 'error'
|
|
|
+ })
|
|
|
+ reject(res)
|
|
|
+ }
|
|
|
+ resolve(res)
|
|
|
+ },
|
|
|
+ error => {
|
|
|
+ this.$message({
|
|
|
+ message: error,
|
|
|
+ type: "error"
|
|
|
+ });
|
|
|
+ reject(error)
|
|
|
+ }
|
|
|
+ )
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 获取项目分类工时占比表
|
|
|
+ async getProjectWoekScale() {
|
|
|
+ let params = {
|
|
|
+ startDate: this.rangeDatas[0],
|
|
|
+ endDate: this.rangeDatas[1],
|
|
|
+ onlyShowWarning: 0
|
|
|
+ }
|
|
|
+ this.listLoading = true
|
|
|
+ let { data } = await this.postData('/project/getMembProjectCateRatio', params)
|
|
|
+ let { categoryList, userList } = data
|
|
|
+ categoryList.push({
|
|
|
+ id: 999999,
|
|
|
+ name: '未分类'
|
|
|
+ })
|
|
|
+ this.listLoading = false
|
|
|
+ this.projectCateRatioList = {
|
|
|
+ categoryList,
|
|
|
+ userList
|
|
|
+ }
|
|
|
+ this.projectCateRatioListKey++
|
|
|
+ },
|
|
|
+ // 获取设置预警
|
|
|
+ async getForewarningTableList() {
|
|
|
+ const { companyId } = this.user
|
|
|
+ this.warningTableLoading = true
|
|
|
+ let { data } = await this.postData('/category-ratio-tbl-setting/get', { companyId })
|
|
|
+ const { monitorCategoryId, moreOrLess, ratio } = data
|
|
|
+ this.warningFrom = {
|
|
|
+ companyId,
|
|
|
+ monitorCategoryId,
|
|
|
+ moreOrLess: moreOrLess || 0,
|
|
|
+ ratio: ratio || 0
|
|
|
+ }
|
|
|
+ this.warningTableLoading = false
|
|
|
+ },
|
|
|
+ // 设置预警
|
|
|
+ async setForewarning() {
|
|
|
+ this.warningTableLoading = true
|
|
|
+ await this.postData('/category-ratio-tbl-setting/update', this.warningFrom)
|
|
|
+ this.getProjectWoekScale()
|
|
|
+ this.setWarningModal = false
|
|
|
+ this.warningTableLoading = false
|
|
|
+ },
|
|
|
+ // 获取分类工时明细表
|
|
|
+ async getHoursDetailClass() {
|
|
|
+ let params = {
|
|
|
+ // 日期, 项目分类
|
|
|
+ }
|
|
|
+ console.log('开始调用分类工时明细表', this.dateSelect)
|
|
|
+ return
|
|
|
+ this.listLoading = true
|
|
|
+ let { data } = await this.postData('/project/getMembProjectCateRatio', params)
|
|
|
+ let { categoryList, userList } = data
|
|
|
+ categoryList.push({
|
|
|
+ name: '未分类'
|
|
|
+ })
|
|
|
+ this.listLoading = false
|
|
|
+ this.projectCateRatioList = {
|
|
|
+ categoryList,
|
|
|
+ userList
|
|
|
+ }
|
|
|
+ },
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
|
<style scoped>
|
|
|
+.sliderSetup {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ .text {
|
|
|
+ color: #409EFF;
|
|
|
+ margin-right: 20px;
|
|
|
+ }
|
|
|
+}
|
|
|
.tableRightBtn {
|
|
|
float: right;
|
|
|
margin-left: 15px !important;
|
|
@@ -3100,6 +3318,7 @@ export default {
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
z-index: 2;
|
|
|
+ margin-top: 5px;
|
|
|
}
|
|
|
.headine h3 {
|
|
|
margin: 0;
|