Browse Source

升级

master
陈裕财 4 years ago
parent
commit
d321c2a87d
  1. 6
      src/views/xm/core/xmIteration/XmIterationInfo.vue
  2. 397
      src/views/xm/core/xmPhase/XmPhaseAdd.vue
  3. 1772
      src/views/xm/core/xmPhase/XmPhaseBatch.vue
  4. 404
      src/views/xm/core/xmPhase/XmPhaseEdit.vue
  5. 1290
      src/views/xm/core/xmPhase/XmPhaseForProduct.vue
  6. 1328
      src/views/xm/core/xmPhase/XmPhaseMng.vue
  7. 576
      src/views/xm/core/xmPhase/XmPhaseOverview.vue
  8. 484
      src/views/xm/core/xmPhase/XmPhaseSelect.vue
  9. 6
      src/views/xm/core/xmProduct/XmProductInfo.vue

6
src/views/xm/core/xmIteration/XmIterationInfo.vue

@ -65,8 +65,7 @@
import xmCost from '../xmProject/XmProjectCost';
import xmBudget from '../xmProject/XmProjectBudgetCost';
import xmContract from '../xmContract/XmContractMng';
import xmEnvList from '../xmProjectEnvList/XmProjectEnvListMng';
import xmPhaseMng from '../xmPhase/XmPhaseMng';
import xmEnvList from '../xmProjectEnvList/XmProjectEnvListMng';
import xmMenuMng from '../xmMenu/XmMenuMng';
import xmMenuWithPlan from '../xmMenu/XmMenuWithPlan';
import xmProjectStateMng from '../xmProjectState/XmProjectStateMng';
@ -283,8 +282,7 @@
},//end methods
components: {
xmTaskMng,
xmPhaseMng,
xmTaskMng,
xmGroupMng,
xmExchange,
xmQuestion,

397
src/views/xm/core/xmPhase/XmPhaseAdd.vue

@ -1,397 +0,0 @@
<template>
<section class="page-container padding">
<el-row class="page-main ">
<!--新增界面 XmPhase xm_project_phase-->
<el-form :model="addForm" label-width="120px" :rules="addFormRules" ref="addForm">
<el-row class="border padding">
<el-form-item label="计划名称" prop="name">
<el-input v-model="addForm.name" placeholder="计划名称" ></el-input>
</el-form-item>
<el-form-item label="序号" prop="seqNo">
<el-input v-model="addForm.seqNo" style="width:50%;" placeholder="排序序号,值越小越靠前,如1.0,2.0等"></el-input>
<el-checkbox true-label="1" false-label="0" v-model="addForm.milestone">标记为里程碑</el-checkbox>
</el-form-item>
<el-form-item label="计划类型" prop="planType">
<el-select v-model="addForm.planType">
<el-option v-for="i in this.dicts.planType" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="任务类型" prop="taskType">
<el-select v-model="addForm.taskType">
<el-option v-for="i in this.dicts.taskType" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" rows="4" v-model="addForm.remark" placeholder="备注" ></el-input>
</el-form-item>
</el-row>
<el-tabs v-model="activeName" class="border padding">
<el-tab-pane label="工作量及人力成本" name="budgetWorkload">
<el-row>
<el-row class="padding-20 border">
<el-row class="padding">工作量计算方式<font style="color:red">总工时 = 工作日天数 * 每日工时数 * 人数 </font> </el-row>
<el-row class="padding">金额计算方式 <font style="color:red">总金额 = 总工时 * 工时单价 </font></el-row>
</el-row>
<el-row class="padding-20 border">
预计时间<el-date-picker
v-model="dateRanger"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="计划开始日期"
end-placeholder="计划完成日期"
value-format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00','23:59:59']"
:picker-options="pickerOptions"
></el-date-picker>
预估工期<el-input style="width:100px;" type="number" v-model="addForm.budgetHours" :precision="2" :step="8" :min="0" placeholder="预计工时"></el-input>小时
<div class="tips"><font>工时{{autoParams.budgetHours}}小时,工作日{{autoParams.weekday}}</font></div>
</el-row>
<el-row class="padding-20 border">
<el-col :span="4">人员类型</el-col>
<el-col :span="4">人数</el-col>
<el-col :span="4">工作量(人时)</el-col>
<el-col :span="4">单价(/人时)</el-col>
<el-col :span="8">总价()</el-col>
</el-row>
<el-row class="padding-20 border">
<el-col :span="4">内购</el-col>
<el-col :span="4"><el-input style="width:100px;" type="number" v-model="addForm.budgetIuserCnt" :precision="0" :step="1" :min="0" placeholder="内购人数"></el-input>
</el-col>
<el-col :span="4">{{autoParams.budgetIuserWorkload}}人时</el-col>
<el-col :span="4"><el-input style="width:100px;" type="number" v-model="addForm.budgetIuserPrice" :precision="0" :step="1" :min="0" placeholder="预计内部人时单价"></el-input> </el-col>
<el-col :span="8">{{this.toFixed(autoParams.budgetIuserAt)}},{{this.toFixed(autoParams.budgetIuserAt/10000)}} 万元</el-col>
</el-row>
<el-row class="padding-20 border">
<el-col :span="4">外购</el-col>
<el-col :span="4"><el-input style="width:100px;" type="number" v-model="addForm.budgetOuserCnt" :precision="0" :step="1" :min="0" placeholder="外购人数"></el-input>
</el-col>
<el-col :span="4">{{autoParams.budgetOuserWorkload}}人时</el-col>
<el-col :span="4"><el-input style="width:100px;" type="number" v-model="addForm.budgetOuserPrice" :precision="0" :step="1" :min="0" placeholder="预计外购人时单价"></el-input> </el-col>
<el-col :span="4">{{autoParams.budgetOuserAt }} {{autoParams.budgetOuserAt/10000 }}万元</el-col>
</el-row >
<el-row class="padding-20 border">
<el-col :span="4">合计</el-col>
<el-col :span="4"> {{autoParams.budgetOuserCnt+autoParams.budgetIuserCnt}}
</el-col>
<el-col :span="4">{{autoParams.budgetOuserWorkload+autoParams.budgetIuserWorkload }}人时,{{ (autoParams.budgetOuserWorkload+autoParams.budgetIuserWorkload)/8/20 }}人月 </el-col>
<el-col :span="4">{{ (parseFloat2(autoParams.budgetOuserPrice) + parseFloat2(autoParams.budgetIuserPrice))/2}}/人时</el-col>
<el-col :span="8">{{autoParams.budgetTotalCost}} {{(autoParams.budgetTotalCost)/10000}} 万元</el-col>
</el-row>
<el-row class="padding-20 border">
总计 {{parseFloat2(addForm.budgetIuserAt)+parseFloat2(addForm.budgetOuserAt)+parseFloat2(addForm.budgetNouserAt)}} <el-tag>{{this.toFixed(autoParams.budgetTotalCost/10000)}}万元</el-tag>
</el-row>
</el-row>
</el-tab-pane>
<el-tab-pane v-if="activeName=='budgetWorkload'" label="收起" name="">
</el-tab-pane>
</el-tabs>
</el-form>
</el-row>
<el-row class="page-bottom">
<el-button @click.native="handleCancel">取消</el-button>
<el-button v-loading="load.add" type="primary" @click.native="addSubmit" :disabled="load.add==true">提交</el-button>
</el-row>
</section>
</template>
<script>
import util from '@/common/js/util';//
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { addXmPhase } from '@/api/xm/core/xmPhase';
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters([
'userInfo','roles'
]),
autoParams:function(){
var budgetOuserPrice=this.toFixed(this.addForm.budgetOuserPrice)
var budgetIuserPrice=this.toFixed(this.addForm.budgetIuserPrice)
var budgetOuserCnt=this.toFixed(this.addForm.budgetOuserCnt)
var budgetIuserCnt=this.toFixed(this.addForm.budgetIuserCnt)
var budgetHours=this.toFixed(this.addForm.budgetHours )
var budgetNouserAt=this.toFixed(this.addForm.budgetNouserAt )
if(budgetOuserPrice==null || budgetOuserPrice==''){
budgetOuserPrice=100
}
if(budgetIuserPrice==null || budgetIuserPrice==''){
budgetIuserPrice=80
}
if(budgetOuserCnt==null || budgetOuserCnt==''){
budgetOuserCnt=0.0
}
if(budgetIuserCnt==null || budgetIuserCnt==''){
budgetIuserCnt=0.0
}
if(budgetNouserAt==null || budgetNouserAt==''){
budgetNouserAt=0.0
}
if(budgetHours==null || budgetHours==''){
budgetHours=0.0
}
var autoParams={
}
var weekday=1;
if(this.dateRanger!=null && this.dateRanger.length>=2 ){
weekday=this.getWeekday(new Date(this.dateRanger[0]),new Date(this.dateRanger[1]));
budgetHours=weekday * 8
}
autoParams.weekday=weekday
autoParams.budgetHours=budgetHours
autoParams.budgetOuserPrice=budgetOuserPrice
autoParams.budgetIuserPrice=budgetIuserPrice
autoParams.budgetOuserCnt=budgetOuserCnt
autoParams.budgetIuserCnt=budgetIuserCnt
autoParams.budgetIuserWorkload= budgetIuserCnt*budgetHours
autoParams.budgetOuserWorkload= budgetOuserCnt*budgetHours
autoParams.budgetWorkload= budgetIuserCnt*budgetHours + budgetOuserCnt*budgetHours
autoParams.budgetOuserAt= budgetOuserCnt * budgetHours * budgetOuserPrice
autoParams.budgetIuserAt= budgetIuserCnt * budgetHours * budgetIuserPrice
autoParams.budgetNouserAt= budgetNouserAt
autoParams.budgetTotalCost= autoParams.budgetOuserAt + autoParams.budgetIuserAt + autoParams.budgetNouserAt
return autoParams
},
},
props:['xmPhase','visible','parentProjectPhase'],
watch: {
'xmPhase':function( xmPhase ) {
this.addForm = xmPhase;
},
'visible':function(visible) {
if(visible==true){
//
if(this.parentProjectPhase){
if(this.parentProjectPhase.children){
this.addForm.seqNo=this.parentProjectPhase.seqNo+"."+(this.parentProjectPhase.children.length+1)
}else{
this.addForm.seqNo=this.parentProjectPhase.seqNo+"."+1
}
}
}
},
autoParams:function(autoParams){
this.fillbudgetHoursToField()
this.fillbudgetAtToField()
}
},
data() {
const beginDate = new Date();
const endDate = new Date();
endDate.setTime(beginDate.getTime() + 3600 * 1000 * 24 * 7 * 4);
return {
dicts:{},// params=[{categoryId:'0001',itemCode:'sex'}] {'sex':[{optionValue:'1',optionName:'',seqOrder:'1',fp:'',isDefault:'0'},{optionValue:'2',optionName:'',seqOrder:'2',fp:'',isDefault:'0'}]}
load:{ list: false, edit: false, del: false, add: false },//...
addFormRules: {
id: [
//{ required: true, message: '', trigger: 'blur' }
],
name: [
{ required: true, message: '计划名称不能为空', trigger: 'blur' }
],
planType: [
{ required: true, message: '请选择计划类型', trigger: 'blur' }
],
taskType: [
{ required: true, message: '请选择任务类型', trigger: 'blur' }
],
seqNo: [
{ required: true, message: '序号不能为空', trigger: 'blur' }
],
},
// xm_project_phase
addForm: {
id:'',name:'',remark:'',parentPhaseId:'',branchId:'',taskType:'kf',planType:'m1',projectId:'',beginDate:'',endDate:'',budgetHours:'',budgetStaffNu:'',ctime:'',budgetNouserAt:'',budgetIuserAt:'',budgetOuserAt:'',baselineId:'',bizProcInstId:'',bizFlowState:'',budgetWorkload:'',totalActWorkload:'',totalActNouserAt:'',totalActInerUserAt:'',totalActOuserAt:'',planType:'',taskType:'',seqNo:'1',budgetIuserCnt:'',budgetOuserCnt:'',budgetIuserPrice:80,budgetOuserPrice:100,budgetIuserWorkload:0,budgetOuserWorkload:0,ntype:'0'
},
dateRanger: [
util.formatDate(beginDate, "yyyy-MM-dd HH:mm:ss"),
util.formatDate(endDate, "yyyy-MM-dd HH:mm:ss")
],
/**begin 在下面加自定义属性,记得补上面的一个逗号**/
pickerOptions: util.getPickerOptions('datarange'),
activeName:'',
costVisible:false,
/**end 在上面加自定义属性**/
}//end return
},//end data
methods: {
// @cancel="addFormVisible=false"
handleCancel:function(){
//this.$refs['addForm'].resetFields();
this.$emit('cancel');
},
//XmPhase xm_project_phase @submit="afteraddSubmit"
addSubmit: function () {
if (
this.dateRanger != null &&
this.dateRanger.length == 2
) {
if(this.dateRanger[0]){
if(this.dateRanger[0].length<=10){
this.addForm.beginDate = this.dateRanger[0] ;
}else{
this.addForm.beginDate = this.dateRanger[0]
}
}
if(this.dateRanger[1]){
if(this.dateRanger[1].length<=10){
this.addForm.endDate = this.dateRanger[1] ;
}else{
this.addForm.endDate = this.dateRanger[1]
}
}
}else{
this.$notify({position:'bottom-left',showClose:true,message: "请输入开始日期和结束日期", type: 'error' });
return;
}
if(!this.addForm.budgetIuserCnt){
this.$notify({position:'bottom-left',showClose:true,message: "内购人员数不能为空", type: 'error' });
return;
}
if(!this.addForm.budgetHours){
this.$notify({position:'bottom-left',showClose:true,message: "工期不能为空", type: 'error' });
return;
}
if(!this.addForm.budgetIuserPrice){
this.$notify({position:'bottom-left',showClose:true,message: "内购单价不能为空", type: 'error' });
return;
}
this.$refs.addForm.validate((valid) => {
if (valid) {
this.$confirm('确认提交吗?', '提示', {}).then(() => {
this.load.add=true
let params = Object.assign({}, this.addForm);
if(!params.budgetIuserAt){
params.budgetIuserAt= this.parseFloat2(params.budgetIuserCnt) * this.parseFloat2(params.budgetIuserPrice) * this.parseFloat2(params.budgetHours)
}
if( !params.budgetOuserAt ){
params.budgetOuserAt= this.parseFloat2(params.budgetOuserCnt) * this.parseFloat2(params.budgetOuserPrice) * this.parseFloat2(params.budgetHours)
}
params.budgetIuserWorkload= this.parseFloat2(params.budgetIuserCnt) * this.parseFloat2(params.budgetHours)
params.budgetOuserWorkload= this.parseFloat2(params.budgetOuserCnt) * this.parseFloat2(params.budgetHours)
params.budgetWorkload= this.parseFloat2(params.budgetIuserWorkload) + this.parseFloat2(params.budgetOuserWorkload)
if( !params.budgetStaffNu ){
params.budgetStaffNu= this.parseFloat2(params.budgetOuserCnt) + this.parseFloat2(params.budgetIuserCnt)
}
if(this.parentProjectPhase==null || this.parentProjectPhase==undefined){
}else{
params.parentPhaseId=this.parentProjectPhase.id
}
var func=addXmPhase;
if(addForm.phaseClass=='1'){
func=addXmPhase
}
func(params).then((res) => {
this.load.add=false
var tips=res.data.tips;
if(tips.isOk){
//this.$refs['addForm'].resetFields();
this.$emit('submit',res.data.data);// @submit="afteraddSubmit"
}
this.$notify({position:'bottom-left',showClose:true,message: tips.msg, type: tips.isOk?'success':'error' });
}).catch( err => this.load.add=false);
});
}
});
},
getWeekday(first, last) {
//getDay()
//firstlast()
first = first.getTime();
last = last.getTime();
var count = 0;
for (var i = first; i <= last; i += 24 * 3600 * 1000) {
var d = new Date(i);
if (d.getDay() >= 1 && d.getDay() <= 5) {
count++;
}
}
return count;
},
toFixed(floatValue,num){
if(floatValue ==null || floatValue=='' || floatValue == undefined){
return 0;
}else{
if(!num){
num=2
}
return parseFloat(parseFloat(floatValue).toFixed(num));
}
},
parseFloat2(floatValue){
if(floatValue ==null || floatValue=='' || floatValue == undefined){
return 0;
}else{
return parseFloat(floatValue);
}
},
fillToField:function(){
this.addForm=Object.assign(this.addForm,this.autoParams);
},
fillbudgetHoursToField:function(){
this.addForm.budgetHours=this.toFixed(this.autoParams.budgetHours)
},
fillbudgetAtToField:function(){
this.addForm.budgetNouserAt=this.toFixed(this.autoParams.budgetNouserAt)
this.addForm.budgetOuserAt=this.toFixed(this.autoParams.budgetOuserAt )
this.addForm.budgetIuserAt=this.toFixed(this.autoParams.budgetIuserAt )
this.addForm.budgetTotalCost=this.toFixed(this.autoParams.budgetTotalCost)
},
/**end 在上面加自定义方法**/
},//end method
components: {
// 'xm-phase-add':XmPhaseEdit
},
mounted() {
this.addForm=Object.assign(this.addForm, this.xmPhase);
/**在下面写其它函数***/
if(this.parentProjectPhase){
if(this.parentProjectPhase.childrenCnt){
this.addForm.seqNo=this.parentProjectPhase.seqNo+"."+(this.parentProjectPhase.childrenCnt+1)
}else{
this.addForm.seqNo=this.parentProjectPhase.seqNo+"."+1
}
}
initSimpleDicts('all',['planType','taskType']).then(res=>{
this.dicts=res.data.data;
})
}//end mounted
}
</script>
<style scoped>
.padding-20{
padding-left: 10px;
padding-right: 10px;
padding-top: 20px;
padding-bottom: 20px;
}
</style>

1772
src/views/xm/core/xmPhase/XmPhaseBatch.vue
File diff suppressed because it is too large
View File

404
src/views/xm/core/xmPhase/XmPhaseEdit.vue

@ -1,404 +0,0 @@
<template>
<section class="page-container padding">
<el-row class="page-main ">
<el-tabs>
<el-tab-pane label="计划详情">
<!--新增界面 XmPhase xm_project_phase-->
<el-form :model="editForm" label-width="120px" :rules="editFormRules" ref="editForm">
<el-row class="border padding">
<el-steps :active="parseInt(editForm.phaseStatus)+1" simple finish-status="success" align-center>
<el-step v-for="(item,index) in statusList" @click.native="on_click(item.id)" :title="item.name" :key="index"></el-step>
</el-steps>
</el-row>
<el-row class="border padding">
<el-form-item label="计划名称" prop="name">
<el-input v-model="editForm.name" placeholder="计划名称" ></el-input>
</el-form-item>
<el-form-item label="序号" prop="seqNo">
<el-input v-model="editForm.seqNo" style="width:50%;" placeholder="排序序号,值越小越靠前,如1.0,2.0等"></el-input>
<el-checkbox true-label="1" false-label="0" v-model="editForm.milestone">标记为里程碑</el-checkbox>
</el-form-item>
<el-form-item label="任务类型" prop="taskType">
<el-select v-model="editForm.taskType">
<el-option v-for="i in this.dicts.taskType" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="计划类型" prop="planType">
<el-select v-model="editForm.planType">
<el-option v-for="i in this.dicts.planType" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" rows="4" v-model="editForm.remark" placeholder="备注" ></el-input>
</el-form-item>
</el-row>
<el-tabs v-model="activeName" class="border padding">
<el-tab-pane label="工作量及人力成本" name="budgetWorkload">
<el-row>
<el-row class="padding-20 border">
<el-row class="padding">工作量计算方式<font style="color:red">总工时 = 工作日天数 * 每日工时数 * 人数 </font> </el-row>
<el-row class="padding">金额计算方式 <font style="color:red">总金额 = 总工时 * 工时单价 </font></el-row>
</el-row>
<el-row class="padding-20 border">
预计时间<el-date-picker
v-model="dateRanger"
type="daterange"
align="right"
unlink-panels
range-separator="至"
start-placeholder="计划开始日期"
end-placeholder="计划完成日期"
value-format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00','23:59:59']"
:picker-options="pickerOptions"
></el-date-picker>
预估工期<el-input style="width:100px;" type="number" v-model="editForm.budgetHours" :precision="2" :step="8" :min="0" placeholder="预计工时"></el-input>小时
<div class="tips"><font>工时{{autoParams.budgetHours}}小时,工作日{{autoParams.weekday}}</font></div>
</el-row>
<el-row class="padding-20 border">
<el-col :span="4">人员类型</el-col>
<el-col :span="4">人数</el-col>
<el-col :span="4">工作量(人时)</el-col>
<el-col :span="4">单价(/人时)</el-col>
<el-col :span="8">总价()</el-col>
</el-row>
<el-row class="padding-20 border">
<el-col :span="4">内购</el-col>
<el-col :span="4"><el-input style="width:100px;" type="number" v-model="editForm.budgetIuserCnt" :precision="0" :step="1" :min="0" placeholder="内购人数"></el-input>
</el-col>
<el-col :span="4">{{autoParams.budgetIuserWorkload}}人时</el-col>
<el-col :span="4"><el-input style="width:100px;" type="number" v-model="editForm.budgetIuserPrice" :precision="0" :step="1" :min="0" placeholder="预计内部人时单价"></el-input> </el-col>
<el-col :span="8">{{this.toFixed(autoParams.budgetIuserAt)}},{{this.toFixed(autoParams.budgetIuserAt/10000)}} 万元</el-col>
</el-row>
<el-row class="padding-20 border">
<el-col :span="4">外购</el-col>
<el-col :span="4"><el-input style="width:100px;" type="number" v-model="editForm.budgetOuserCnt" :precision="0" :step="1" :min="0" placeholder="外购人数"></el-input>
</el-col>
<el-col :span="4">{{autoParams.budgetOuserWorkload}}人时</el-col>
<el-col :span="4"><el-input style="width:100px;" type="number" v-model="editForm.budgetOuserPrice" :precision="0" :step="1" :min="0" placeholder="预计外购人时单价"></el-input> </el-col>
<el-col :span="4">{{autoParams.budgetOuserAt }} {{autoParams.budgetOuserAt/10000 }}万元</el-col>
</el-row >
<el-row class="padding-20 border">
<el-col :span="4">合计</el-col>
<el-col :span="4"> {{autoParams.budgetOuserCnt+autoParams.budgetIuserCnt}}
</el-col>
<el-col :span="4">{{autoParams.budgetOuserWorkload+autoParams.budgetIuserWorkload }}人时,{{ (autoParams.budgetOuserWorkload+autoParams.budgetIuserWorkload)/8/20 }}人月 </el-col>
<el-col :span="4">{{ (parseFloat2(autoParams.budgetOuserPrice) + parseFloat2(autoParams.budgetIuserPrice))/2}}/人时</el-col>
<el-col :span="8">{{autoParams.budgetTotalCost}} {{(autoParams.budgetTotalCost)/10000}} 万元</el-col>
</el-row>
<el-row class="padding-20 border">
总计 {{parseFloat2(editForm.budgetIuserAt)+parseFloat2(editForm.budgetOuserAt)+parseFloat2(editForm.budgetNouserAt)}} <el-tag>{{this.toFixed(autoParams.budgetTotalCost/10000)}}万元</el-tag>
</el-row>
</el-row>
</el-tab-pane>
<el-tab-pane v-if="activeName=='budgetWorkload'" label="收起" name="">
</el-tab-pane>
</el-tabs>
</el-form>
</el-tab-pane>
<el-tab-pane label="计划概览" lazy>
<xm-phase-overview :xm-phase="xmPhase"></xm-phase-overview>
</el-tab-pane>
</el-tabs>
</el-row>
<el-row class="page-bottom">
<el-button @click.native="handleCancel">取消</el-button>
<el-button v-loading="load.edit" type="primary" @click.native="editSubmit" :disabled="load.edit==true">提交</el-button>
</el-row>
</section>
</template>
<script>
import util from '@/common/js/util';//
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { editXmPhase } from '@/api/xm/core/xmPhase';
import { mapGetters } from 'vuex'
import XmPhaseOverview from './XmPhaseOverview';//
export default {
computed: {
...mapGetters([
'userInfo','roles'
]),
autoParams:function(){
var budgetOuserPrice=this.toFixed(this.editForm.budgetOuserPrice)
var budgetIuserPrice=this.toFixed(this.editForm.budgetIuserPrice)
var budgetOuserCnt=this.toFixed(this.editForm.budgetOuserCnt)
var budgetIuserCnt=this.toFixed(this.editForm.budgetIuserCnt)
var budgetHours=this.toFixed(this.editForm.budgetHours )
var budgetNouserAt=this.toFixed(this.editForm.budgetNouserAt )
if(budgetOuserPrice==null || budgetOuserPrice==''){
budgetOuserPrice=100
}
if(budgetIuserPrice==null || budgetIuserPrice==''){
budgetIuserPrice=80
}
if(budgetOuserCnt==null || budgetOuserCnt==''){
budgetOuserCnt=0.0
}
if(budgetIuserCnt==null || budgetIuserCnt==''){
budgetIuserCnt=0.0
}
if(budgetNouserAt==null || budgetNouserAt==''){
budgetNouserAt=0.0
}
if(budgetHours==null || budgetHours==''){
budgetHours=0.0
}
var autoParams={
}
var weekday=1;
if(this.dateRanger!=null && this.dateRanger.length>=2 ){
weekday=this.getWeekday(new Date(this.dateRanger[0]),new Date(this.dateRanger[1]));
budgetHours=weekday * 8
}
autoParams.weekday=weekday
autoParams.budgetHours=budgetHours
autoParams.budgetOuserPrice=budgetOuserPrice
autoParams.budgetIuserPrice=budgetIuserPrice
autoParams.budgetOuserCnt=budgetOuserCnt
autoParams.budgetIuserCnt=budgetIuserCnt
autoParams.budgetIuserWorkload= budgetIuserCnt*budgetHours
autoParams.budgetOuserWorkload= budgetOuserCnt*budgetHours
autoParams.budgetWorkload= budgetIuserCnt*budgetHours + budgetOuserCnt*budgetHours
autoParams.budgetOuserAt= budgetOuserCnt * budgetHours * budgetOuserPrice
autoParams.budgetIuserAt= budgetIuserCnt * budgetHours * budgetIuserPrice
autoParams.budgetNouserAt= budgetNouserAt
autoParams.budgetTotalCost= autoParams.budgetOuserAt + autoParams.budgetIuserAt + autoParams.budgetNouserAt
return autoParams
},
},
props:['xmPhase','visible','parentProjectPhase'],
watch: {
'xmPhase':function( xmPhase ) {
this.editForm = xmPhase;
this.dateRanger=[this.editForm.beginDate,this.editForm.endDate]
},
'visible':function(visible) {
if(visible==true){
//
}
},
autoParams:function(autoParams){
this.fillbudgetHoursToField()
this.fillbudgetAtToField()
}
},
data() {
const beginDate = new Date();
const endDate = new Date();
endDate.setTime(beginDate.getTime() + 3600 * 1000 * 24 * 7 * 4);
return {
dicts:{},// params=[{categoryId:'0001',itemCode:'sex'}] {'sex':[{optionValue:'1',optionName:'',seqOrder:'1',fp:'',isDefault:'0'},{optionValue:'2',optionName:'',seqOrder:'2',fp:'',isDefault:'0'}]}
load:{ list: false, add: false, del: false, edit: false },//...
editFormRules: {
id: [
//{ required: true, message: '', trigger: 'blur' }
],
name: [
{ required: true, message: '计划名称不能为空', trigger: 'blur' }
],
planType: [
{ required: true, message: '请选择计划类型', trigger: 'blur' }
],
taskType: [
{ required: true, message: '请选择任务类型', trigger: 'blur' }
],
seqNo: [
{ required: true, message: '序号不能为空', trigger: 'blur' }
]
},
oldeditForm:{},
// xm_project_phase
editForm: {
id:'',name:'',remark:'',parentPhaseId:'',branchId:'',taskType:'kf',planType:'m1',projectId:'',beginDate:'',endDate:'',budgetHours:'',budgetStaffNu:'',ctime:'',budgetNouserAt:'',budgetIuserAt:'',budgetOuserAt:'',baselineId:'',bizProcInstId:'',bizFlowState:'',budgetWorkload:'',totalActWorkload:'',totalActNouserAt:'',totalActInerUserAt:'',totalActOuserAt:'',seqNo:'1',budgetIuserCnt:'',budgetOuserCnt:'',budgetIuserPrice:80,budgetOuserPrice:100,budgetIuserWorkload:0,budgetOuserWorkload:0,phaseStatus:'',ntype:'0'
},
dateRanger: [
],
/**begin 在下面加自定义属性,记得补上面的一个逗号**/
pickerOptions: util.getPickerOptions('datarange'),
activeName:'',
costVisible:false,
statusList:[
{id:'0',name:'初始'},
{id:'1',name:'执行中'},
{id:'2',name:'完工'},
{id:'3',name:'关闭'},
{id:'4',name:'删除中'},
{id:'5',name:'已删除'},
{id:'6',name:'暂停'}
]
/**end 在上面加自定义属性**/
}//end return
},//end data
methods: {
// @cancel="editFormVisible=false"
handleCancel:function(){
//this.$refs['editForm'].resetFields();
this.$emit('cancel');
},
//XmPhase xm_project_phase @submit="aftereditSubmit"
editSubmit: function () {
if (
this.dateRanger != null &&
this.dateRanger.length == 2
) {
if(this.dateRanger[0]){
if(this.dateRanger[0].length<=10){
this.editForm.beginDate = this.dateRanger[0] ;
}else{
this.editForm.beginDate = this.dateRanger[0]
}
}
if(this.dateRanger[1]){
if(this.dateRanger[1].length<=10){
this.editForm.endDate = this.dateRanger[1] ;
}else{
this.editForm.endDate = this.dateRanger[1]
}
}
}else{
this.$notify({position:'bottom-left',showClose:true,message: "请输入开始日期和结束日期", type: 'error' });
return;
}
if(!this.editForm.budgetIuserCnt){
this.$notify({position:'bottom-left',showClose:true,message: "内购人员数不能为空", type: 'error' });
return;
}
if(!this.editForm.budgetHours){
this.$notify({position:'bottom-left',showClose:true,message: "工期不能为空", type: 'error' });
return;
}
if(!this.editForm.budgetIuserPrice){
this.$notify({position:'bottom-left',showClose:true,message: "内购单价不能为空", type: 'error' });
return;
}
this.$refs.editForm.validate((valid) => {
if (valid) {
this.$confirm('确认提交吗?', '提示', {}).then(() => {
this.load.edit=true
let params = Object.assign({}, this.editForm);
if(!params.budgetIuserAt){
params.budgetIuserAt= this.parseFloat2(params.budgetIuserCnt) * this.parseFloat2(params.budgetIuserPrice) * this.parseFloat2(params.budgetHours)
}
if( !params.budgetOuserAt ){
params.budgetOuserAt= this.parseFloat2(params.budgetOuserCnt) * this.parseFloat2(params.budgetOuserPrice) * this.parseFloat2(params.budgetHours)
}
params.budgetIuserWorkload= this.parseFloat2(params.budgetIuserCnt) * this.parseFloat2(params.budgetHours)
params.budgetOuserWorkload= this.parseFloat2(params.budgetOuserCnt) * this.parseFloat2(params.budgetHours)
params.budgetWorkload= this.parseFloat2(params.budgetIuserWorkload) + this.parseFloat2(params.budgetOuserWorkload)
if( !params.budgetStaffNu ){
params.budgetStaffNu= this.parseFloat2(params.budgetOuserCnt) + this.parseFloat2(params.budgetIuserCnt)
}
var func=editXmPhase
if(this.editForm.phaseClass=="1"){
func=editXmPhase
}
func(params).then((res) => {
this.load.edit=false
var tips=res.data.tips;
if(tips.isOk){
//this.$refs['editForm'].resetFields();
this.$emit('submit',res.data.data);// @submit="aftereditSubmit"
}
this.$notify({position:'bottom-left',showClose:true,message: tips.msg, type: tips.isOk?'success':'error' });
}).catch( err => this.load.edit=false);
});
}
});
},
getWeekday(first, last) {
//getDay()
//firstlast()
first = first.getTime();
last = last.getTime();
var count = 0;
for (var i = first; i <= last; i += 24 * 3600 * 1000) {
var d = new Date(i);
if (d.getDay() >= 1 && d.getDay() <= 5) {
count++;
}
}
return count;
},
toFixed(floatValue,num){
if(floatValue ==null || floatValue=='' || floatValue == undefined){
return 0;
}else{
if(!num){
num=2
}
return parseFloat(parseFloat(floatValue).toFixed(num));
}
},
parseFloat2(floatValue){
if(floatValue ==null || floatValue=='' || floatValue == undefined){
return 0;
}else{
return parseFloat(floatValue);
}
},
fillToField:function(){
this.editForm=Object.assign(this.editForm,this.autoParams);
},
fillbudgetHoursToField:function(){
this.editForm.budgetHours=this.toFixed(this.autoParams.budgetHours)
},
fillbudgetAtToField:function(){
this.editForm.budgetNouserAt=this.toFixed(this.autoParams.budgetNouserAt)
this.editForm.budgetOuserAt=this.toFixed(this.autoParams.budgetOuserAt )
this.editForm.budgetIuserAt=this.toFixed(this.autoParams.budgetIuserAt )
this.editForm.budgetTotalCost=this.toFixed(this.autoParams.budgetTotalCost)
},
on_click(status){
this.editForm.phaseStatus=status;
}
/**end 在上面加自定义方法**/
},//end method
components: {
XmPhaseOverview,
// 'xm-phase-edit':XmPhaseEdit
},
mounted() {
this.editForm=Object.assign(this.editForm, this.xmPhase);
/**在下面写其它函数***/
this.dateRanger=[this.editForm.beginDate,this.editForm.endDate]
initSimpleDicts('all',['planType','taskType']).then(res=>{
this.dicts=res.data.data;
})
}//end mounted
}
</script>
<style scoped>
.padding-20{
padding-left: 10px;
padding-right: 10px;
padding-top: 20px;
padding-bottom: 20px;
}
</style>

1290
src/views/xm/core/xmPhase/XmPhaseForProduct.vue
File diff suppressed because it is too large
View File

1328
src/views/xm/core/xmPhase/XmPhaseMng.vue
File diff suppressed because it is too large
View File

576
src/views/xm/core/xmPhase/XmPhaseOverview.vue

@ -1,576 +0,0 @@
<template>
<section>
<el-row class="page-main " style="overflow-x: hidden;">
<el-row style="margin-bottom:10px">
<el-card class="box-card" style="padding:0px ;height:100px">
<div>
<el-row style="padding:10px">
<el-steps :active="this.xmPhase.phaseStatus" finish-status="success" align-center>
<el-step title="初始"></el-step>
<el-step title="执行中"></el-step>
<el-step title="完工"></el-step>
<el-step title="关闭"></el-step>
<el-step title="删除中"></el-step>
<el-step title="已删除"></el-step>
<el-step title="暂停"></el-step>
</el-steps>
</el-row>
</div>
</el-card>
</el-row>
<el-row :gutter="10" style="margin-bottom:10px">
<el-col :span="12" >
<el-card class="box-card" style="padding:0px ;height:425px">
<div slot="header" class="clearfix">
<span>计划信息</span>
</div>
<el-row style="margin-bottom:18px">
<el-row>
<span v-text="this.xmPhase.mngUsername"></span>
</el-row>
<el-row>
<span>计划管理员</span>
</el-row>
</el-row>
<el-row style="margin-bottom:18px">
<el-col :span="8" @click="">
<div class="item">
<div class="icon" style="background-color: rgb(79, 140, 255);">
<i class="el-icon-right"></i>
</div>
<div class="info">
<div v-text="this.xmPhase.taskCnt"></div>
<div class="title">总任务量</div>
</div>
</div>
</el-col>
<el-col :span="8">
<div class="item">
<div class="icon" style="background-color: rgb(255, 153, 51);">
<i class="el-icon-loading"></i>
</div>
<div class="info">
<div v-text="notStart">
</div>
<div class="title">待完成</div>
</div>
</div>
</el-col>
<el-col :span="8">
<div class="item">
<div class="icon" style="background-color: rgb(0, 153, 51);">
<i class="el-icon-check"></i>
</div>
<div class="info">
<div v-text="this.xmPhase.taskFinishCnt" >
</div>
<div class="title">已完成</div>
</div>
</div>
</el-col>
</el-row>
<el-row style="margin-bottom:18px">
<div class="item">
<div class="icon2" style="background-color: rgb(204, 204, 204);">
<i class="el-icon-date"></i>
</div>
<div class="info">
<div v-text="phaseBeginDate+'~'+phaseEndDate">
</div>
<div class="title">计划周期</div>
</div>
</div>
</el-row>
<el-row style="margin-bottom:18px">
<div class="item">
<div class="icon2" style="background-color: rgb(204, 204, 204);">
<i class="el-icon-star-off"></i>
</div>
<div class="info">
<div class="title"> 创建时间 {{this.phaseCreateDate}}</div>
</div>
</div>
</el-row>
<el-row style="margin-bottom:18px">
<div class="item">
<div class="icon2" style="background-color: rgb(204, 204, 204);">
<i class="el-icon-refresh"></i>
</div>
<div class="info">
<div class="title"> 关联迭代数 {{(this.xmPhase.iterationCnt)}} </div>
</div>
</div>
</el-row>
<el-row style="margin-bottom:18px">
<div class="item">
<div class="icon2" style="background-color: rgb(204, 204, 204);">
<i class="el-icon-alarm-clock"></i>
</div>
<div>
<div class="progress-item">
<el-progress :percentage="taskProgress"></el-progress>
<div class="title">任务进度</div>
</div>
</div>
</div>
</el-row>
</el-card>
</el-col>
<el-col :span="12" >
<el-card class="box-card" style="padding:0px ;height:425px">
<div slot="header" class="clearfix">
<span>计划工时</span>
</div>
<div>
<el-row style="padding:25px;">
<div class="item">
<el-col :span="8">
<div>
<div style="text-align:center;">
<span style="font-size:24px;" v-text="this.xmPhase.budgetWorkload"></span>
<span style="font-size:5px;">h</span>
</div>
<div style="text-align:center;font-size:5px;">预估工时</div>
</div>
</el-col>
<el-col :span="8">
<div>
<div style="text-align:center;">
<span style="font-size:24px;" v-text="this.xmPhase.actWorkload"></span>
<span style="font-size:5px;">h</span>
</div>
<div style="text-align:center;font-size:5px;">登记工时</div>
</div>
</el-col>
<el-col :span="8">
<div>
<div style="text-align:center;">
<span style="font-size:24px;" v-text="workloadProgress"></span>
<span style="font-size:5px;">%</span>
</div>
<div style="text-align:center;font-size:5px;">工时进度</div>
</div>
</el-col>
</div>
</el-row>
<el-row style="padding:25px;">
<div class="item">
<el-col :span="8">
<div>
<div style="text-align:center;">
<span style="font-size:24px;" v-text="remainWorkload"></span>
<span style="font-size:5px;">h</span>
</div>
<div style="text-align:center;font-size:5px;">剩余工时</div>
</div>
</el-col>
<el-col :span="8">
<div>
<div style="text-align:center;">
<span style="font-size:24px;" v-text="deviation"></span>
<span style="font-size:5px;">h</span>
</div>
<div style="text-align:center;font-size:5px;">预估偏差</div>
</div>
</el-col>
<el-col :span="8">
<div>
<div style="text-align:center;">
<span style="font-size:24px;" v-text="deviationRate"></span>
<span style="font-size:5px;">%</span>
</div>
<div style="text-align:center;font-size:5px;">预估偏差率</div>
</div>
</el-col>
</div>
</el-row>
<el-row>
<span style="margin-left:20px;">项目预计进度</span>
<el-progress style="width: 90%;margin-left:20px;margin-top: 10px;margin-bottom: 20px;" :text-inside="true" :stroke-width="24" :percentage="planProgress"></el-progress>
</el-row>
<el-row>
<span style="margin-left:20px;">项目实际进度</span>
<el-progress style="width: 90%;margin-left:20px;margin-top: 10px;" :text-inside="true" :stroke-width="24" :percentage="realProgress"></el-progress>
</el-row>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="10" style="margin-bottom:10px">
<el-col :span="12" >
<el-card class="box-card" style="height:425px">
<div slot="header" class="clearfix">
<span>总预算情况</span>
</div>
<div style="'100%'">
<div id="costPieChart" :style="{width: '100%', height: '300px'}"></div>
</div>
</el-card>
</el-col>
<el-col :span="12" >
<el-card class="box-card" style="height:425px">
<div slot="header" class="clearfix">
<span>工作量分布</span>
</div>
<div>
<div id="workloadPie" :style="{width: '100%', height: '300px'}"></div>
</div>
</el-card>
</el-col>
</el-row>
</el-row>
</section>
</template>
<script>
import util from '@/common/js/util';//
//import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['userInfo','roles']),
notStart: function() {
return this.xmPhase.taskCnt-this.xmPhase.taskFinishCnt;
},
taskProgress: function (){
if(this.xmPhase.actRate){
return this.xmPhase.actRate;
}else{
return 0;
}
},
phaseBeginDate: function (){
if(this.xmPhase.beginDate){
return this.xmPhase.beginDate.substring(0,10);
} else{
return '暂无';
}
},
phaseEndDate: function (){
if(this.xmPhase.endDate){
return this.xmPhase.endDate.substring(0,10);
} else{
return '暂无';
}
},
phaseCreateDate: function (){
if(this.xmPhase.ctime){
return this.xmPhase.ctime.substring(0,10);
} else{
return '暂无';
}
},
workloadProgress:function (){
return Math.round(this.xmPhase.actWorkload/this.xmPhase.budgetWorkload*100);
},
deviation:function (){
let now = new Date();
let startTime = new Date(this.xmPhase.beginDate);
let endTime = new Date(this.xmPhase.endDate);
if(now<=endTime){
let allDays=endTime-startTime;
return this.xmPhase.budgetWorkload - Math.round((now-startTime)/allDays*this.xmPhase.budgetWorkload)
}else{
return this.xmPhase.actWorkload - this.xmPhase.budgetWorkload;
}
},
deviationRate:function (){
return Math.round(this.deviation/this.xmPhase.budgetWorkload*100);
},
remainWorkload:function (){
return this.xmPhase.budgetWorkload - this.xmPhase.actWorkload;
},
planProgress:function (){
let now = new Date();
let startTime = new Date(this.xmPhase.beginDate);
let endTime = new Date(this.xmPhase.endDate);
if(now<=endTime){
let allDays=endTime-startTime;
return Math.round((now-startTime)/allDays*100)
}else{
return 100;
}
},
realProgress:function (){
if(this.xmPhase.actWorkload < this.xmPhase.budgetWorkload){
return Math.round(this.xmPhase.actWorkload/this.xmPhase.budgetWorkload*100)
}else{
return 100;
}
},
xmPhaseCpd(){
return this.xmPhase
},
},
props:['xmPhase'],
watch:{
xmPhaseCpd:function(){
this.drawCostPie();
this.drawWorkloadPie();
}
},
data() {
return {
};
},
methods:{
drawCostPie() {
let costPieChart = this.$echarts.init(document.getElementById("costPieChart"));
let option = {
tooltip: {
trigger: 'item',
formatter: '{b} : {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 'left',
},
series: [
{
center:['55%','40%'],//
type: 'pie',
radius: '50%',//
label:{ //
normal:{
show:true,
position:'outer', //:
textStyle : {
fontWeight : 100 ,
fontSize: document.body.clientWidth / 120, //
color: "#000000"
},
formatter:'{b}\n{c}({d}%)',//bname,c:value,d:
alignTo:'edge',
margin:10
}
},
data: [
{value: this.xmPhase.budgetNouserAt,
itemStyle: {
normal:{
color: '#5470C6'
}
},
name: '非人力'},
{value: this.xmPhase.budgetIuserAt,
itemStyle: {
normal:{
color: '#73C0DE'
}
},
name: '内部人力'},
{value: this.xmPhase.budgetOuserAt,
itemStyle: {
normal:{
color: '#99CCFF'
}
},
name: '外购人力'},
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
//
costPieChart.setOption(option);
},
drawWorkloadPie() {
let workloadPie = this.$echarts.init(document.getElementById("workloadPie"));
let option = {
tooltip: {
trigger: 'item',
formatter: '{b} : {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 'left',
},
series: [
{
center:['55%','40%'],//
type: 'pie',
radius: '50%',//
label:{ //
normal:{
show:true,
position:'outer', //:
textStyle : {
fontWeight : 100 ,
fontSize: document.body.clientWidth / 120, //
color: "#000000"
},
formatter:'{b}\n{c}({d}%)',//bname,c:value,d:
alignTo:'edge',
margin:10
}
},
data: [
{value: this.xmPhase.budgetIuserWorkload,
itemStyle: {
normal:{
color: '#5470C6'
}
},
name: '内部人力'},
{value: this.xmPhase.budgetOuserWorkload,
itemStyle: {
normal:{
color: '#73C0DE'
}
},
name: '外购人力'},
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
};
//
workloadPie.setOption(option);
},
},
mounted() {
this.$nextTick(() => {
});
this.drawCostPie();
this.drawWorkloadPie();
},
};
</script>
<style scoped lang="scss">
.container {
margin: 10px;
}
.header {
display: flex;
justify-content: flex-start;
padding: 10px;
span {
padding-right: 15px;
}
}
.col {
margin-bottom: 20px;
}
.icon {
color: #fff;
height: 30px;
width: 30px;
border-radius: 15px;
text-align: center;
line-height: 30px;
font-size: 20px;
display: inline-block;
margin-right: 5px;
}
.icon2 {
color: #000000;
height: 30px;
width: 30px;
border-radius: 15px;
text-align: center;
line-height: 30px;
font-size: 20px;
display: inline-block;
margin-right: 5px;
margin-left: 5px;
}
.item {
display: flex;
justify-content: flex-start;
position: relative;
.progress-item{
position:absolute; width:80%;
}
}
.card-font {
color: #000000;
font-size: 12px;
.el-col {
margin-bottom: 20px;
}
}
.calendar-header {
display: flex;
justify-content: space-between;
.cal-header-boxs {
flex: 1;
display: flex;
justify-content: flex-end;
.cal-header-box {
padding: 5px;
height: 45px;
margin-left: 10px;
}
.box-icon {
text-align: center;
}
.box-info {
text-align: center;
font-size: 12px;
color: #000000;
}
}
}
.el-tag:hover {
cursor: pointer;
}
.value {
cursor: pointer;
}
.reference {
margin-top: 10px;
font-size: 12px;
}
.click {
background: #e9f7ff;
}
.calendar-box {
display: flex;
justify-content: flex-start;
}
</style>
<style>
.app-container{
padding: 20px;
padding-bottom: 0;
}
</style>

484
src/views/xm/core/xmPhase/XmPhaseSelect.vue

@ -1,484 +0,0 @@
<template>
<section>
<el-row>
<el-table lazy :load="loadXmPhaseLazy" :height="tableHeight" ref="selectPhaseTable" :data="projectPhaseTreeData" :show-summary="false" row-key="id" :tree-props="{children: 'children', hasChildren: 'childrenCnt'}" @sort-change="sortChange" highlight-current-row v-loading="load.list" border @selection-change="selsChange" @row-click="rowClick" style="width: 100%;">
<el-table-column prop="name" label="计划名称" show-overflow-tooltip>
<template slot="header" slot-scope="scope">
<span>计划 <el-tag type="warning" v-if="editForm.id" closable @close="clearSelectPhase()"> <font class="hidden-md-and-down">{{editForm.name}}</font><font class="hidden-lg-and-up" style="font-size:2px;">{{editForm.name}}</font></el-tag></span>
</template>
<template slot-scope="scope">
<span class="vlink">{{scope.row.seqNo}} &nbsp;<el-tooltip v-if="scope.row.milestone=='1'" content="里程碑"><i class="el-icon-star-on"></i></el-tooltip>{{scope.row.name}}
<font :color="scope.row.actRate>=100?'green':'#FF8C00'"> {{ (scope.row.actRate!=null?scope.row.actRate:0)+'%'}} </font>
</span>
</template>
</el-table-column>
</el-table>
<el-pagination layout=" total, prev, next" @current-change="handleCurrentChange" @size-change="handleSizeChange" :page-sizes="[10,20, 50, 100, 500]" :current-page="pageInfo.pageNum" :page-size="pageInfo.pageSize" :total="pageInfo.total" style="float:right;"></el-pagination>
</el-row>
</section>
</template>
<script>
import util from '@/common/js/util';//
//import Sticky from '@/components/Sticky' // header
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmPhase } from '@/api/xm/core/xmPhase';
import {sn} from '@/common/js/sequence'
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters([
'userInfo','roles'
]),
projectPhaseTreeData() {
let xmPhases = this.xmPhases
var projectPhaseTreeData = this.translateDataToTree(xmPhases);
return projectPhaseTreeData;
},
},
props:['selProject','xmIteration'],
watch:{
selProject:function(selProject,old){
if(!selProject){
this.xmPhases=[]
}else{
if( ( !old && selProject.id) || (old && selProject.id!=old.id)){
this.searchXmPhases();
}
}
},
xmIteration(){
this.searchXmPhases();
}
},
data() {
return {
filters: {
key: ''
},
xmPhases: [],//
pageInfo:{//
total:0,//0>0
pageSize:50,//
count:false,//
pageNum:1,//1
orderFields:[],// ['sex','student_id']
orderDirs:[]// asc,desc ['asc','desc']
},
load:{ list: false, edit: false, del: false, add: false },//...
sels: [],//
dicts:{
xmPhaseStatus:[],
},// params=[{categoryId:'0001',itemCode:'sex'}] {'sex':[{optionValue:'1',optionName:'',seqOrder:'1',fp:'',isDefault:'0'},{optionValue:'2',optionName:'',seqOrder:'2',fp:'',isDefault:'0'}]}
addFormVisible: false,//xmPhase
//xmPhase
addForm: {
id:'',name:'',remark:'',parentPhaseId:'',branchId:'',taskType:'kf',planType:'m1',projectId:'',beginDate:'',endDate:'',budgetHours:'',budgetStaffNu:'',ctime:'',budgetNouserAt:'',budgetIuserAt:'',budgetOuserAt:'',baselineId:'',bizProcInstId:'',bizFlowState:'',budgetIuserCnt:'',budgetOuserCnt:'',seqNo:'',budgetIuserPrice:80,budgetOuserPrice:100,budgetIuserWorkload:0,budgetOuserWorkload:0
},
editFormVisible: false,//
//xmPhase
editForm: {
id:'',name:'',remark:'',parentPhaseId:'',branchId:'',projectId:'',beginDate:'',endDate:'',budgetHours:'',budgetStaffNu:'',ctime:'',budgetNouserAt:'',budgetIuserAt:'',budgetOuserAt:'',baselineId:'',bizProcInstId:'',bizFlowState:'',budgetIuserCnt:'',budgetOuserCnt:'',seqNo:'',budgetIuserPrice:80,budgetOuserPrice:100,budgetIuserWorkload:0,budgetOuserWorkload:0
},
editFormInit: {
id:'',name:'',remark:'',parentPhaseId:'',branchId:'',taskType:'kf',planType:'m1',projectId:'',beginDate:'',endDate:'',budgetHours:'',budgetStaffNu:'',ctime:'',budgetNouserAt:'',budgetIuserAt:'',budgetOuserAt:'',baselineId:'',bizProcInstId:'',bizFlowState:'',budgetIuserCnt:'',budgetOuserCnt:'',seqNo:'',budgetIuserPrice:80,budgetOuserPrice:100,budgetIuserWorkload:0,budgetOuserWorkload:0
},
parentProjectPhase:null,
/**begin 自定义属性请在下面加 请加备注**/
phaseTemplateVisible:false,
xmRecordVisible:false,
valueChangeRows:[],
batchEditVisible:false,
menuVisible:false,//
pickerOptions: util.getPickerOptions('date'),
gstcVisible:false,
tableHeight:300,
ganrrColumns: {
children: 'children',
name: 'name',
id: 'id',
pid: 'parentPhaseId',
startDate: 'beginDate',
endDate: 'endDate',
},
/**end 自定义属性请在上面加 请加备注**/
}
},//end data
methods: {
handleSizeChange(pageSize) {
this.pageInfo.pageSize=pageSize;
this.getXmPhases();
},
handleCurrentChange(pageNum) {
this.pageInfo.pageNum = pageNum;
this.getXmPhases();
},
// obj.order=ascending/descending, asc/desc ; obj.prop=,
sortChange( obj ){
var dir='asc';
if(obj.order=='ascending'){
dir='asc'
}else{
dir='desc';
}
if(obj.prop=='xxx'){
this.pageInfo.orderFields=['xxx'];
this.pageInfo.orderDirs=[dir];
}
this.getXmPhases();
},
searchXmPhases(){
this.pageInfo.count=true;
this.getXmPhases();
},
getParams(params){
if(this.filters.key){
params.key='%'+this.filters.key+'%'
}
if(this.selProject!=null && this.selProject!=undefined){
params.projectId=this.selProject.id
}
if(this.xmIteration){
params.iterationId=this.xmIteration.id
}
if(this.xmProduct){
params.productId=this.xmProduct.id
}
if(this.filters.milestone){
params.milestone=this.filters.milestone
}
if(this.filters.isKeyPath){
params.isKeyPath=this.filters.isKeyPath
}
if(this.filters.phaseStatus){
params.phaseStatus=this.filters.phaseStatus
}
if(!(params.isKeyPath||params.milestone||params.productId||params.iterationId||params.phaseStatus)){
params.isTop="1"
}
return params;
},
loadXmPhaseLazy(row, treeNode, resolve) {
if(row.children&&row.children.length>0){
resolve(row.children)
}else{
var params={parentPhaseId:row.id}
params=this.getParams(params);
params.isTop=""
this.load.list = true;
var func=listXmPhase
func(params).then(res=>{
this.load.list = false
var tips = res.data.tips;
if(tips.isOk){
resolve(res.data.data)
}else{
resolve([])
}
}).catch( err => this.load.list = false );
}
},
// XmPhase xm_project_phase
getXmPhases() {
let params = {
pageSize: this.pageInfo.pageSize,
pageNum: this.pageInfo.pageNum,
total: this.pageInfo.total,
count:this.pageInfo.count
};
if(this.pageInfo.orderFields!=null && this.pageInfo.orderFields.length>0){
let orderBys=[];
for(var i=0;i<this.pageInfo.orderFields.length;i++){
orderBys.push(this.pageInfo.orderFields[i]+" "+this.pageInfo.orderDirs[i])
}
params.orderBy= orderBys.join(",")
}
params=this.getParams(params)
params.withParents="1"
this.load.list = true;
listXmPhase(params).then((res) => {
var tips=res.data.tips;
if(tips.isOk){
this.pageInfo.total = res.data.total;
this.pageInfo.count=false;
this.xmPhases = res.data.data;
}else{
this.$notify({position:'bottom-left',showClose:true,message: tips.msg, type: 'error' });
}
this.load.list = false;
}).catch( err => this.load.list = false );
},
//xmPhase
selsChange: function (sels) {
this.sels = sels;
},
clearSelectPhase(){
this.editForm=this.editFormInit
this.$emit('clear-select',null );// @row-click="rowClick"
},
rowClick: function(row, event, column){
var myrow=JSON.parse(JSON.stringify(row))
myrow.children=[];
this.parentProjectPhase=myrow
this.editForm=row;
this.$emit('row-click',myrow, event, column);// @row-click="rowClick"
},
/**begin 自定义函数请在下面加**/
translateDataToTree(data2) {
var data=JSON.parse(JSON.stringify(data2));
let parents = data.filter(value =>{
//
if(value.parentPhaseId == 'undefined' || value.parentPhaseId == null || value.parentPhaseId == ''){
return true;
//
}else if(data.some(i=>value.parentPhaseId==i.id)){
return false;
}else {
return true
}
})
let children = data.filter(value =>{
if(data.some(i=>value.parentPhaseId==i.id)){
return true;
}else{
return false;
}
})
let translator = (parents, children) => {
parents.forEach((parent) => {
children.forEach((current, index) => {
if (current.parentPhaseId === parent.id) {
let temp = JSON.parse(JSON.stringify(children))
temp.splice(index, 1)
translator([current], temp)
typeof parent.children !== 'undefined' ? parent.children.push(current) : parent.children = [current]
}
}
)
}
)
}
translator(parents, children)
return parents
},
getFloatValue(value,digit){
if(value==null || value=='' || value==undefined){
value=0;
return value;
}
if(!digit){
digit=2
}
if(typeof( value )=='string'){
return parseFloat(value);
}else{
return value
}
},
formatDate(dateStr){
if(dateStr==null || dateStr==""){
return "";
}else{
return dateStr.substr(0,10);
}
},
calcTaskStateByTime(startTime,endTime,actRate,phaseStatus){
if(startTime==null || startTime=="" || endTime==null || endTime ==""){
return {remark:"未配置日期",status:'warning'}
}
var curDate=new Date();
var start=new Date(startTime);
var end=new Date(endTime);
if(this.getDaysBetween(curDate, start)<=0){
return {remark:this.toFixed(this.getDaysBetween(start,curDate))+"天后开始",status:'primary'};
}else if( this.getDaysBetween(curDate, start) > 0 && this.getDaysBetween(curDate, end) <= 0 ){
return {remark: this.toFixed(this.getDaysBetween(end, curDate))+"天后结束",status:'primary'};
}else if( this.getDaysBetween(curDate, end) > 0 ){
return {remark:"逾期"+( this.toFixed(this.getDaysBetween(curDate, end)) )+"天",status:'danger'};
}
},
/**
* 计算两个日期之间的天数
* @param dateString1 开始日期 yyyy-MM-dd
* @param dateString2 结束日期 yyyy-MM-dd
*/
getDaysBetween(startDate,endDate){
if (startDate==endDate){
return 0;
}
var days=(startDate - endDate )/(1*24*60*60*1000);
return days;
},
getSummariesForBatchEdit:function(params){
const { columns, data } = params;
const sums = [];
sums[0]=''
sums[1]='总计'//
sums[2]=''//
sums[3]=''//
sums[4]=''//
var workload=this.budgetData.budgetIuserWorkload+this.budgetData.budgetOuserWorkload
var cost=this.budgetData.budgetNouserAt+this.budgetData.budgetIuserAt+this.budgetData.budgetOuserAt
sums[4]='工作量:'+workload.toFixed(0)+'人时,预算金额:'+cost.toFixed(0)+'元,'+(cost/10000).toFixed(2)+'万元'
return sums;
},
getSummariesForNoBatchEdit:function(params){
const { columns, data } = params;
const sums = [];
sums[0]=''
sums[1]=''//
sums[2]='总计'//
sums[3]=''//
sums[4]=''//
sums[5]=''//
sums[6]=''//
var budgetWorkload=this.budgetData.budgetIuserWorkload+this.budgetData.budgetOuserWorkload
var actWorkload=this.budgetData.actWorkload
var budgetCost=this.budgetData.budgetNouserAt+this.budgetData.budgetIuserAt+this.budgetData.budgetOuserAt
var actCost=this.budgetData.actIuserAt+this.budgetData.actNouserAt+this.budgetData.actOuserAt
sums[5]='预算工作量:'+budgetWorkload+'人时,实际:'+actWorkload+'人时'
sums[6]='预算金额:'+budgetCost.toFixed(0)+'元,'+(budgetCost/10000).toFixed(2)+'万元,实际:'+actCost.toFixed(0)+'元,'+(actCost/10000).toFixed(2)+'万元'
return sums;
},
toFixed(floatValue,xsd){
if(floatValue ==null || floatValue=='' || floatValue == undefined){
return 0;
}else{
if(xsd){
if(typeof(floatValue)=='number'){
return floatValue.toFixed(xsd)
}else{
return parseFloat(floatValue).toFixed(xsd);
}
}else{
if(typeof(floatValue)=='number'){
return floatValue.toFixed(0)
}else{
return parseFloat(floatValue).toFixed(0);
}
}
}
},
showLog(row){
this.editForm=row
this.xmRecordVisible=true
},
//
// dict sIdmenuId; ePmeuId menuId;
judgePmenuId(dict, sId, ePmeuId) {
if (sId === ePmeuId) {
return true;
} else if (dict[ePmeuId]) {
return this.judgePmenuId(dict, sId, dict[ePmeuId]);
} else {
return false;
}
},
changePmenuId(sId, eId) {
let dict = {};
this.xmPhases.forEach(d => {
dict[d.id] = d.parentPhaseId || '';
});
if (!dict[eId]) {
this.xmPhases.find(d => {
if (d.id === sId) {
d.parentPhaseId = eId;
console.log('更新关系1');
this.fieldChange(d,'parentPhaseId',true);
}
})
} else {
const isSynezesis = this.judgePmenuId(dict, sId, dict[eId]);
if (!isSynezesis) {
this.xmPhases.find(d => {
if (d.id === sId) {
d.parentPhaseId = eId;
console.log('更新关系2');
this.fieldChange(d,'parentPhaseId',true);
}
})
} else {
console.log('形成闭合回路--拖拽不更新');
}
}
},
/**end 自定义函数请在上面加**/
formateOption:function(itemCode,value){
if(this.dicts[itemCode]){
var dicts=this.dicts[itemCode].filter(i=>i.id==value);
if(dicts && dicts.length > 0){
return dicts[0].name
}else{
return value;
}
}else{
return value
}
},
},//end methods
components: {
//
},
mounted() {
this.$nextTick(() => {
this.tableHeight = util.calcTableMaxHeight(this.$refs.selectPhaseTable.$el);
if(this.selProject){
this.getXmPhases();
}
initSimpleDicts('all',['xmPhaseStatus']).then(res=>{
this.dicts=res.data.data;
})
});
}
}
</script>
<style lang="scss" scoped>
.align-right{
float: right;
}
</style>

6
src/views/xm/core/xmProduct/XmProductInfo.vue

@ -210,8 +210,7 @@
import xmCost from '../xmProject/XmProjectCost';
import xmBudget from '../xmProject/XmProjectBudgetCost';
import xmContract from '../xmContract/XmContractMng';
import xmEnvList from '../xmProjectEnvList/XmProjectEnvListMng';
import xmPhaseForProduct from '../xmPhase/xmPhaseForProduct';
import xmEnvList from '../xmProjectEnvList/XmProjectEnvListMng';
import xmMenuWithPlan from '../xmMenu/XmMenuWithPlan';
import xmProjectStateMng from '../xmProjectState/XmProjectStateMng';
import xmTestCaseExecMng from '../xmTestCaseExec/XmTestCaseExecMng';
@ -429,8 +428,7 @@ import XmMenuBox from '../xmMenu/XmMenuBox.vue';
},//end methods
components: {
xmTaskMng,
xmPhaseForProduct,
xmTaskMng,
xmGroupMng,
xmExchange,
xmQuestion,

Loading…
Cancel
Save