xiejiahao 4 years ago
parent
commit
e97987409b
  1. 4
      src/api/xm/core/xmQuestion.js
  2. 30
      src/api/xm/core/xmTaskSbill.js
  3. 30
      src/api/xm/core/xmTaskWorkload.js
  4. 17
      src/router/routes_xm.js
  5. 66
      src/views/mdp/arc/tag/TagDialog.vue
  6. 3
      src/views/xm/XmOverview2.vue
  7. 127
      src/views/xm/core/components/XmItSelect.vue
  8. 318
      src/views/xm/core/components/XmIterationSelect.vue
  9. 119
      src/views/xm/core/components/XmMenuWorkload.vue
  10. 424
      src/views/xm/core/components/XmProductSelect.vue
  11. 357
      src/views/xm/core/components/XmProjectSelect.vue
  12. 98
      src/views/xm/core/components/XmTableConfig.vue
  13. 66
      src/views/xm/core/xmGroup/XmGroupDialog.vue
  14. 22
      src/views/xm/core/xmGroup/XmGroupMng.vue
  15. 32
      src/views/xm/core/xmGroup/XmGroupSelect.vue
  16. 12
      src/views/xm/core/xmIteration/XmIterationAdd.vue
  17. 3
      src/views/xm/core/xmIteration/XmIterationEdit.vue
  18. 11
      src/views/xm/core/xmIteration/XmIterationForLinkComplex.vue
  19. 3
      src/views/xm/core/xmIteration/XmIterationInfo.vue
  20. 49
      src/views/xm/core/xmIteration/XmIterationMng.vue
  21. 384
      src/views/xm/core/xmIteration/XmIterationSelect.vue
  22. 4
      src/views/xm/core/xmIterationLink/XmIterationLinkForProduct.vue
  23. 5
      src/views/xm/core/xmIterationLink/XmIterationLinkForProject.vue
  24. 93
      src/views/xm/core/xmIterationMenu/XmIterationMenuMng.vue
  25. 6
      src/views/xm/core/xmMenu/XmMenuAdd.vue
  26. 40
      src/views/xm/core/xmMenu/XmMenuEdit.vue
  27. 217
      src/views/xm/core/xmMenu/XmMenuMng.vue
  28. 163
      src/views/xm/core/xmMenu/XmMenuSelect.vue
  29. 19
      src/views/xm/core/xmProduct/XmProductForLinkComplex.vue
  30. 3
      src/views/xm/core/xmProduct/XmProductInfo.vue
  31. 12
      src/views/xm/core/xmProduct/XmProductMng.vue
  32. 347
      src/views/xm/core/xmProduct/XmProductSelect.vue
  33. 29
      src/views/xm/core/xmProductProjectLink/XmProductProjectLinkMng.vue
  34. 537
      src/views/xm/core/xmProject/XmProjectAdd.vue
  35. 296
      src/views/xm/core/xmProject/XmProjectEdit.vue
  36. 10
      src/views/xm/core/xmProject/XmProjectForLink.vue
  37. 18
      src/views/xm/core/xmProject/XmProjectForLinkComplex.vue
  38. 3
      src/views/xm/core/xmProject/XmProjectInfo.vue
  39. 293
      src/views/xm/core/xmProject/XmProjectList.vue
  40. 24
      src/views/xm/core/xmProject/XmProjectMng.vue
  41. 2
      src/views/xm/core/xmProject/XmProjectOverviewComplex.vue
  42. 198
      src/views/xm/core/xmProject/XmProjectSelect.vue
  43. 22
      src/views/xm/core/xmProjectState/XmProjectStateMng.vue
  44. 23
      src/views/xm/core/xmQuestion/XmQuestionAdd.vue
  45. 53
      src/views/xm/core/xmQuestion/XmQuestionEdit.vue
  46. 330
      src/views/xm/core/xmQuestion/XmQuestionMng.vue
  47. 2
      src/views/xm/core/xmTask/XmTaskAgileKanban.vue
  48. 4
      src/views/xm/core/xmTask/XmTaskList.vue
  49. 6
      src/views/xm/core/xmTask/XmTaskMng.vue
  50. 135
      src/views/xm/core/xmTaskSbill/SelectXmProject.vue
  51. 217
      src/views/xm/core/xmTaskSbill/XmTaskSbillEdit.vue
  52. 265
      src/views/xm/core/xmTaskSbill/XmTaskSbillMng.vue
  53. 174
      src/views/xm/core/xmTaskWorkload/XmTaskWorkloadEdit.vue
  54. 260
      src/views/xm/core/xmTaskWorkload/XmTaskWorkloadMng.vue
  55. 22
      src/views/xm/core/xmTestCase/XmTestCaseMng.vue
  56. 68
      src/views/xm/core/xmTestCaseExec/XmTestCaseExecMng.vue

4
src/api/xm/core/xmQuestion.js

@ -30,3 +30,7 @@ export const editXmQuestion = params => { return axios.post(`${base}/xm/core/xmQ
export const addXmQuestion = params => { return axios.post(`${base}/xm/core/xmQuestion/add`, params); };
export const editStatus = params => { return axios.post(`${base}/xm/core/xmQuestion/editStatus`, params); };
export const editXmQuestionSomeFields = params => { return axios.post(`${base}/xm/core/xmQuestion/editSomeFields`, params); };

30
src/api/xm/core/xmTaskSbill.js

@ -0,0 +1,30 @@
import axios from '@/utils/request'
import config from '@/common/config'
let base = config.getCoreBasePath();
/**
* 任务结算表
*1 默认只开放普通查询所有查询只要上传 分页参数 {currentPage:当前页码从1开始,pageSize:每页记录数,total:总记录数如果是0后台会自动计算总记录数非0不会自动计算}后台都会自动按分页查询 其它 api用到再打开没用到的api请注释掉
*2 查询新增修改的参数格式 params={id:'结算单据编号 主键',title:'结算单标题',amt:'金额=工时表中结算金额之和',ctime:'创建时间',cuserid:'创建人编号',cusername:'创建人姓名',remark:'备注',branchId:'机构编号',deptid:'部门编号',cpId:'相对方编号(机构写机构号,个人写个人编号)',cpName:'相对方名称(机构写机构名称,个人写个人名称)',workload:'结算工作量=工时表中工时之和',bizMonth:'业务月份yyyy-MM',bizDate:'业务日期yyyy-MM-dd',bizFlowState:'结算流程状态',bizProcInstId:'结算流程实例',ltime:'更新时间',status:'0-待提交,1-已提交,2-已通过,3-已付款,4-已完成',fmsg:'最后审核意见',projectId:'项目编号',projectName:'项目名称'}
**/
//普通查询 条件之间and关系
export const listXmTaskSbill = params => { return axios.get(`${base}/xm/core/xmTaskSbill/list`, { params: params }); };
//模糊查询任务结算表 条件之间or关系
//export const listXmTaskSbillKey = params => { return axios.get(`${base}/xm/core/xmTaskSbill/listKey`, { params: params }); };
//删除一条任务结算表 params={id:'结算单据编号 主键'}
export const delXmTaskSbill = params => { return axios.post(`${base}/xm/core/xmTaskSbill/del`,params); };
//批量删除任务结算表 params=[{id:'结算单据编号 主键'}]
export const batchDelXmTaskSbill = params => { return axios.post(`${base}/xm/core/xmTaskSbill/batchDel`, params); };
//修改一条任务结算表记录
export const editXmTaskSbill = params => { return axios.post(`${base}/xm/core/xmTaskSbill/edit`, params); };
//新增一条任务结算表
export const addXmTaskSbill = params => { return axios.post(`${base}/xm/core/xmTaskSbill/add`, params); };

30
src/api/xm/core/xmTaskWorkload.js

@ -0,0 +1,30 @@
import axios from '@/utils/request'
import config from '@/common/config'
let base = config.getCoreBasePath();
/**
* 工时登记表
*1 默认只开放普通查询所有查询只要上传 分页参数 {currentPage:当前页码从1开始,pageSize:每页记录数,total:总记录数如果是0后台会自动计算总记录数非0不会自动计算}后台都会自动按分页查询 其它 api用到再打开没用到的api请注释掉
*2 查询新增修改的参数格式 params={id:'主键 主键',userid:'员工编号',username:'姓名',ctime:'创建日期',taskId:'业务对象主键任务编号',cuserid:'创建人编号',bizDate:'业务日期yyyy-MM-dd',wstatus:'状态0-待确认,1-已确认,2-无效',remark:'备注',ttype:'任务类型-关联字典taskType',sbillId:'结算单据编号',stime:'结算提交时间',sstatus:'结算状态0-无需结算,1-待结算2-已提交3-已通过4-已结算',amt:'工时对应金额',samt:'结算金额',workload:'工时,一个task_id可多次提交,小时'}
**/
//普通查询 条件之间and关系
export const listXmTaskWorkload = params => { return axios.get(`${base}/xm/core/xmTaskWorkload/list`, { params: params }); };
//模糊查询工时登记表 条件之间or关系
//export const listXmTaskWorkloadKey = params => { return axios.get(`${base}/xm/core/xmTaskWorkload/listKey`, { params: params }); };
//删除一条工时登记表 params={id:'主键 主键'}
export const delXmTaskWorkload = params => { return axios.post(`${base}/xm/core/xmTaskWorkload/del`,params); };
//批量删除工时登记表 params=[{id:'主键 主键'}]
export const batchDelXmTaskWorkload = params => { return axios.post(`${base}/xm/core/xmTaskWorkload/batchDel`, params); };
//修改一条工时登记表记录
export const editXmTaskWorkload = params => { return axios.post(`${base}/xm/core/xmTaskWorkload/edit`, params); };
//新增一条工时登记表
export const addXmTaskWorkload = params => { return axios.post(`${base}/xm/core/xmTaskWorkload/add`, params); };

17
src/router/routes_xm.js

@ -15,8 +15,6 @@ export default {
},
// leaf: true,//只有一个节点
children: [
{ path: 'xmProject/XmProjectAdd', component: _import('xm/core/xmProject/XmProjectAdd'), name: 'xmProjectAdd',hidden:true, meta: { title: '项目立项' }},
{ path: 'xmProject/XmProjectAllMng', component: _import('xm/core/xmProject/XmProjectAllMng'), name: 'xmProjectAllMng', meta: { title: '项目总览' }},
{ path: 'xmProject/XmProjectMng', component: _import('xm/core/xmProject/XmProjectMng'), name: 'xmProjectMng', meta: { title: '项目(我的)' }},
{ path: 'xmProjectState/XmProjectStateMng', component: _import('xm/core/xmProjectState/XmProjectStateMng'), name: 'XmProjectStateMng', meta: { title: '项目统计' }},
@ -151,6 +149,21 @@ export default {
{ path: 'xmGroup/XmGroupAllMng', component: _import('xm/core/xmGroup/XmGroupAllMng'), name: 'XmGroupAllMng', meta: { title: '团队管理' }},
{ path: 'xmGroupUser/XmGroupUserMng', component: _import('xm/core/xmGroupUser/XmGroupUserMng'), name: 'XmGroupUserMng', meta: { title: '成员管理' }},
]
},
{
path: '/xm/core',
component: Layout,
name: 'TaskSbill',
iconCls: 'fa el-icon-menu',
meta: {
menu:true,
title: '任务结算',
icon: 'task'
},
//leaf: true,//只有一个节点
children: [
{ path: 'xmTaskSbill/XmTaskSbillMng', component: _import('xm/core/xmTaskSbill/XmTaskSbillMng'), name: 'XmTaskSbilllMng', meta: { title: '任务结算',icon:'task' }},
]
}
]
}

66
src/views/mdp/arc/tag/TagDialog.vue

@ -0,0 +1,66 @@
<template>
<section>
<el-drawer title="选择标签" :visible.sync="visible" show-close append-to-body size="50%" @close="option=null">
<tag-mng :jump="jump" :tagIds="tagIds" :visible="visible" @select-confirm="onSelectConfirm"></tag-mng>
</el-drawer>
</section>
</template>
<script>
import util from '@/common/js/util'; //
import {
mapGetters
} from 'vuex'
import TagMng from "./TagMng.vue"
export default {
name:"tagDialog",
computed: {
...mapGetters([
'workShop', 'userInfo'
])
},
//
props: ['jump', 'tagIds'],
watch: {
},
data() {
return {
visible:false,
option:null/**{data:'',action:''} */,
}
}, //end data
methods: {
open(option){
this.visible=true;
this.option=option;
},
close(){
this.visible=false;
this.option=null;
},
/**
* @select-confirm
*
*
*/
onSelectConfirm(selectTags){
this.$emit('select-confirm',selectTags,{...this.option})
this.visible=false;
this.option=null;
}
}, //end methods
components: {
TagMng,
},
mounted() {
}
}
</script>
<style scoped>
</style>

3
src/views/xm/XmOverview2.vue

@ -940,7 +940,8 @@ export default {
},
mounted() {
this.searchXmBranchState( this.guiderStart );
//this.searchXmBranchState( this.guiderStart );
this.searchXmBranchState();
this.drawWorkload();
this.drawTaskByDate();
this.drawAllBar();

127
src/views/xm/core/components/XmItSelect.vue

@ -1,127 +0,0 @@
<template>
<el-select v-model="iterationId" placeholder="迭代" @focus="focus" :clearable="clearable">
<el-option v-for="(item,index) in xmIterations" :label="item.iterationName" :value="item.id" :key="index" ></el-option>
</el-select>
</template>
<script>
import util from '@/common/js/util';//
import config from '@/common/config';//
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmIteration,listXmIterationWithState, delXmIteration, batchDelXmIteration,loadTasksToXmIterationState } from '@/api/xm/core/xmIteration';
const map={};
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters([
'userInfo','roles'
]),
},
props:[ 'clearable', 'value', 'productId','linkProjectId','autoSelect'],
watch:{
productId:function(){
this.initData();
},
linkProjectId:function(){
this.initData();
},
value(){
this.iterationId=value;
},
iterationId(){
this.$emit("input",this.iterationId)
if(!this.iterationId){
this.$emit("change",null)
return;
}
var iteration=this.xmIterations.find(i=>i.id==this.iterationId)
this.$emit("change",iteration)
}
},
data() {
return {
load:{list:false,},
iterationId:null,
xmIterations:null,
/**end 自定义属性请在上面加 请加备注**/
}
},//end data
methods: {
focus(){
if(!this.xmIterations){
this.initData()
}
},
searchXmIterations(){
this.getXmIterations();
},
// XmIteration
getXmIterations() {
var params={};
if(this.productId){
params.productId=this.productId
}
if(this.linkProjectId){
params.linkProjectId=this.linkProjectId
}
this.load.list = true;
listXmIterationWithState(params).then((res) => {
var tips=res.data.tips;
if(tips.isOk){
this.xmIterations = res.data.data;
if(this.productId){
map['pd'+this.productId]=res.data.data
}else{
map['pj'+this.linkProjectId]=res.data.data
}
if(this.autoSelect===true&&this.xmIterations.length>0){
var row=this.xmIterations[0];
this.iterationId=row.id
}
}else{
this.$notify({showClose: true, message: tips.msg, type: 'error' });
}
this.load.list = false;
}).catch( err => this.load.list = false );
},
initData(){
if(this.productId){
var xmIterations=map['pd'+this.productId]
if(!xmIterations){
this.getXmIterations();
}else{
this.xmIterations=xmIterations;
}
}else{
if(this.linkProjectId){
var xmIterations=map['pj'+this.linkProjectId]
if(!xmIterations){
this.getXmIterations();
}else{
this.xmIterations=xmIterations;
}
}
}
}
},//end methods
components: {
//
},
mounted() {
this.$nextTick(() => {
//this.initData();
});
}
}
</script>
<style lang="scss" scoped>
</style>

318
src/views/xm/core/components/XmIterationSelect.vue

@ -0,0 +1,318 @@
<template>
<section>
<el-popover style="display:inline;"
placement="bottom"
width="400"
v-model="iterationVisible"
trigger="manual" >
<el-row>
<el-table ref="table" :height="maxTableHeight" :data="xmIterations" row-key="id" @sort-change="sortChange" highlight-current-row v-loading="load.list" border @selection-change="selsChange" @row-click="rowClick" style="width: 100%;">
<el-table-column prop="iterationName" label="迭代" >
<template slot="header" slot-scope="scope">
迭代 &nbsp;&nbsp;&nbsp;
<span style="float:right;">
<el-button v-if="clearable!==false && editForm && editForm.id" type="text" @click="clearSelectIteration">清空</el-button> &nbsp;&nbsp;<el-button type="text" @click="close">关闭</el-button>&nbsp;&nbsp;
<el-popover
placement="top-start"
title=""
v-model="moreVisible"
width="400"
trigger="manual" >
<el-row>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">迭代编号:</font><el-input v-model="filters.id" placeholder="输入迭代编号">
</el-input>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">上线时间:</font>
<el-date-picker
v-model="dateRangerOnline"
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-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">迭代名称:</font><el-input v-model="filters.key" placeholder="模糊查询"></el-input>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<el-button type="text" @click="moreVisible=false">关闭</el-button>
<el-button type="primary" icon="el-icon-search" @click="searchXmIterations">查询</el-button>
</el-col>
</el-row>
<el-button type="text" slot="reference" style="float:right;" @click="moreVisible=!moreVisible" icon="el-icon-search">更多条件</el-button>
</el-popover>
</span>
</template>
<template slot-scope="scope">
{{scope.row.iterationName}} <font :color="calcFinishRate(scope.row)==100?'green':'#FF8C00'">{{calcFinishRate(scope.row)}}%</font>
</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>
<el-link title="点击选中迭代" @click="iterationVisible=!iterationVisible" type="warning" slot="reference" icon="el-icon-search"><font style="font-size:14px;"><slot name="title">{{editForm&&editForm.id?editForm.iterationName:'选择迭代'}}</slot></font></el-link>
</el-popover>
</section>
</template>
<script>
import util from '@/common/js/util';//
import config from '@/common/config';//
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmIteration,listXmIterationWithState, delXmIteration, batchDelXmIteration,loadTasksToXmIterationState } from '@/api/xm/core/xmIteration';
const map=new Map();
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters([
'userInfo','roles'
]),
},
props:['clearable', 'productId', 'linkProjectId','autoSelect'],
watch:{
productId:function(){
this.initData();
},
linkProjectId:function(){
this.initData();
}
},
data() {
const beginDate = new Date();
const endDate = new Date();
beginDate.setTime(beginDate.getTime() - 3600 * 1000 * 24 * 7 * 4 * 12 );
endDate.setTime(endDate.getTime() + 3600 * 1000 * 24 * 7 * 4 * 12 );
return {
filters: {
key: '',
queryScope:'',// iterationId\branchId\compete\''
id:'',//
},
pickerOptions: util.pickerOptions('datarange'),
dateRangerOnline: [
],//线
xmIterations: [],//
pageInfo:{//
total:0,//0>0
pageSize:10,//
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:{
//sex:[],
},// params=[{categoryId:'0001',itemCode:'sex'}] {'sex':[{optionValue:'1',optionName:'',seqOrder:'1',fp:'',isDefault:'0'},{optionValue:'2',optionName:'',seqOrder:'2',fp:'',isDefault:'0'}]}
//xmIteration
addForm: {
id:'',branchId:'',iterationName:'',startTime:'',endTime:'',onlineTime:'',pid:'',adminUserid:'',adminUsername:'',ctime:'',budgetCost:'',budgetWorkload:'',distBudgetCost:'',distBudgetWorkload:'',actCost:'',actWorkload:'',actStaffNum:'',seqNo:'',
},
//xmIteration
editForm: {
id:'',branchId:'',iterationName:'',startTime:'',endTime:'',onlineTime:'',pid:'',adminUserid:'',adminUsername:'',ctime:'',budgetCost:'',budgetWorkload:'',distBudgetCost:'',distBudgetWorkload:'',actCost:'',actWorkload:'',actStaffNum:'',seqNo:'',
},
editFormInit: {
id:'',branchId:'',iterationName:'',startTime:'',endTime:'',onlineTime:'',pid:'',adminUserid:'',adminUsername:'',ctime:'',budgetCost:'',budgetWorkload:'',distBudgetCost:'',distBudgetWorkload:'',actCost:'',actWorkload:'',actStaffNum:'',seqNo:'',
},
/**begin 自定义属性请在下面加 请加备注**/
maxTableHeight:300,
iterationVisible:false,
moreVisible:false,
/**end 自定义属性请在上面加 请加备注**/
}
},//end data
methods: {
handleSizeChange(pageSize) {
this.pageInfo.pageSize=pageSize;
this.getXmIterations();
},
handleCurrentChange(pageNum) {
this.pageInfo.pageNum = pageNum;
this.getXmIterations();
},
// 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.getXmIterations();
},
searchXmIterations(){
this.pageInfo.count=true;
this.getXmIterations();
},
// XmIteration
getXmIterations() {
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(",")
}
if(this.filters.key){
params.key= "%"+this.filters.key+"%"
}
if(this.productId){
params.productId=this.productId
}
if(this.linkProjectId){
params.linkProjectId=this.linkProjectId
}
if(this.dateRangerOnline && this.dateRangerOnline.length==2){
params.onlineTimeStart=this.dateRangerOnline[0]
params.onlineTimeEnd=this.dateRangerOnline[1]
}
this.load.list = true;
listXmIterationWithState(params).then((res) => {
var tips=res.data.tips;
if(tips.isOk){
this.pageInfo.total = res.data.total;
this.pageInfo.count=false;
this.xmIterations = res.data.data;
if(this.productId){
map.set(this.productId,this.xmIterations)
}else if(this.linkProjectId){
map.set(this.linkProjectId,this.xmIterations)
}
if(this.autoSelect===true&&this.xmIterations.length>0){
if(this.autoSelect!==false&&this.xmIterations.length>0 && this.iterationVisible==false){
var row=this.xmIterations[0];
this.$refs.table.setCurrentRow(row);
this.rowClick(row)
}
}
}else{
this.$notify({showClose: true, message: tips.msg, type: 'error' });
}
this.load.list = false;
}).catch( err => this.load.list = false );
},
//xmIteration
selsChange: function (sels) {
this.sels = sels;
},
rowClick: function(row, event, column){
var oldId=this.editForm.id
this.editForm=row
this.iterationVisible=false;
this.moreVisible=false;
if(oldId!=this.editForm.id){
this.$emit("change",row)
}
this.$emit('row-click',row, event, column);// @row-click="rowClick"
},
/**end 自定义函数请在上面加**/
calcFinishRate(row){
if(row.finishRate){
return parseInt(row.finishRate);
}else{
return 0;
}
},
close(){
this.iterationVisible=false;
this.$emit("close")
},
initData(){
if(this.productId){
var xmIterations=map.get(this.productId);
if(xmIterations){
this.xmIterations=xmIterations;
if(this.autoSelect!==false&&this.xmIterations.length>0 && this.iterationVisible==false){
var row=this.xmIterations[0];
this.$refs.table.setCurrentRow(row);
this.rowClick(row)
}
}else{
this.searchXmIterations();
}
}else if(this.linkProjectId){
var xmIterations=map.get(this.linkProjectId);
if(xmIterations){
this.xmIterations=xmIterations;
if(this.autoSelect!==false&&this.xmIterations.length>0 && this.iterationVisible==false){
var row=this.xmIterations[0];
this.$refs.table.setCurrentRow(row);
this.rowClick(row)
}
}else{
this.searchXmIterations();
}
}else{
//his.searchXmIterations();
}
},
clearSelectIteration(){
var oldId=this.editForm.id
this.editForm=this.editFormInit
this.$refs.table.setCurrentRow();
if(oldId!=this.editForm.id){
this.$emit("change",null)
}
this.iterationVisible=false;
this.moreVisible=false;
this.$emit('clear',null );// @row-click="rowClick"
},
},//end methods
components: {
//
},
mounted() {
this.$nextTick(() => {
this.initData();
this.maxTableHeight = util.calcTableMaxHeight(this.$refs.table.$el);
});
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.more-label-font{
text-align:center;
float:left;
padding-top:5px;
}
.font-class{
color: rgba(116, 85, 85, 0.493);
}
.align-right{
float: right;
}
</style>

119
src/views/xm/core/components/XmMenuWorkload.vue

@ -0,0 +1,119 @@
<template>
<section>
<el-popover
placement="bottom"
width="500"
v-model="formVisible"
trigger="manual" > <el-form :model="editForm" label-width="100px" ref="editForm">
<el-form-item label="汇总方式" prop="calcType">
<el-radio v-model="editForm.calcType" label="3" placeholder="下级往上级汇总" :disabled="editForm.ntype!=='0'">下往上</el-radio>
<el-radio v-model="editForm.calcType" label="1" placeholder="由任务汇总" :disabled="editForm.ntype!=='0'">任务汇总</el-radio>
<el-radio v-model="editForm.calcType" label="2" placeholder="手工填报" :disabled="editForm.ntype!=='0'">手工填报</el-radio>
</el-form-item>
<el-form-item label="工时进度" prop="mactRate" >
<el-progress style="width:50%;" :stroke-width="15" :percentage="editForm.mactRate?editForm.mactRate:0"></el-progress>
</el-form-item>
<el-form-item label="预估工期" prop="budgetHours">
<el-input-number :disabled="editForm.calcType!=='2' " style="width:200px;" v-model="editForm.budgetHours" :precision="2" :step="8" :min="0" placeholder="预计工期(小时)"></el-input-number>&nbsp;h
</el-form-item>
<el-form-item label="预估工时" prop="budgetWorkload">
<el-input-number :disabled="editForm.calcType!=='2' " style="width:200px;" v-model="editForm.budgetWorkload" :precision="2" :step="8" :min="0" placeholder="预计工时(人时)"></el-input-number> &nbsp;h
</el-form-item>
<el-form-item label="实际工时" prop="mactWorkload">
<el-input-number :disabled="editForm.calcType!=='2' " style="width:200px;" v-model="editForm.mactWorkload" :precision="2" :step="8" :min="0" placeholder="实际工时(人时)"></el-input-number> &nbsp;h
</el-form-item>
<font color="blue" style="font-size:10px;">控制规则:
<br>下级往上汇总指工时数据按 &nbsp;用户故事->特性->史诗 &nbsp;这样的汇总关系将数据逐级往上汇总
<br>由任务汇总 指用户故事的工时数据由任务汇总
<br>手工填报 指用户故事的工时数据来自手工填报无论是否关联了任务都不从任务汇总
</font>
<el-form-item label="" class="padding">
<el-button type="text" @click="cancel">关闭</el-button>
<el-button :disabled="editForm.calcType!=='2'" type="primary" @click="submit">确认</el-button>
</el-form-item>
</el-form>
<el-button title="点击填写工时" @click="formVisible=!formVisible" type="warning" slot="reference" icon="el-icon-edit"><font style="font-size:14px;"></font></el-button>
</el-popover>
</section>
</template>
<script>
import util from '@/common/js/util';//
import config from '@/common/config';//
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters([
'userInfo','roles'
]),
},
props:['menu'],
watch:{
menu(){
this.editForm={...this.menu}
},
'editForm.mactWorkload':function(val,oldVal){
if(!this.editForm.budgetWorkload){
return;
}
if(val==0||!val){
return;
}
this.editForm.mactRate=Math.round(val/this.editForm.budgetWorkload*100)
if( this.editForm.mactRate>100){
this.editForm.mactRate=100;
}
},
'editForm.budgetWorkload':function(val,oldVal){
if(!this.editForm.mactWorkload){
return;
}
if(val==0||!val){
return;
}
this.editForm.mactRate=Math.round(this.editForm.mactWorkload/val*100)
if( this.editForm.mactRate>100){
this.editForm.mactRate=100;
}
}
},
data() {
return {
editForm: {
menuId:'',menuName:'',pmenuId:'',productId:'',remark:'',status:'',online:'',demandUrl:'',codeUrl:'',designUrl:'',docUrl:'',helpUrl:'',operDocUrl:'',seqNo:'1',mmUserid:'',mmUsername:'',ntype:'0',childrenCnt:0,sinceVersion:'',
proposerId:'',proposerName:'',dlvl:'',dtype:'',priority:'',source:'',calcType:'1',mactWorkload:0,mactAmount:0,mactRate:0
},
formVisible:false,
}
},//end data
methods: {
cancel(){
this.formVisible=false;
this.$emit("cancel")
},
submit(){
var params={mactRate:this.editForm.mactRate,menuId:this.editForm.menuId,mactWorkload:this.editForm.mactWorkload,budgetWorkload:this.editForm.budgetWorkload,budgetHours:this.editForm.budgetHours,calcType:this.editForm.calcType}
this.$emit("submit",params);
this.formVisible=false;
}
},//end methods
components: {
//
},
mounted() {
this.$nextTick(() => {
this.editForm={...this.menu}
});
}
}
</script>
<style lang="scss" scoped>
</style>

424
src/views/xm/core/components/XmProductSelect.vue

@ -0,0 +1,424 @@
<template>
<section>
<el-popover v-if="!dialog"
placement="bottom"
width="400"
trigger="manual"
v-model="productVisible">
<el-row >
<!--列表 XmProduct 产品表-->
<el-table ref="table" :height="maxTableHeight" :data="xmProducts" :row-class-name="tableRowClassName" @sort-change="sortChange" :highlight-current-row="true" current-row-key="id" v-loading="load.list" border @selection-change="selsChange" @row-click="rowClick" style="width: 100%;">
<el-table-column prop="productName" label="产品名称">
<template slot="header" slot-scope="scope">
产品名称
<span style="float:right;">
<el-button type="text" @click="clearSelect">清空</el-button>&nbsp;&nbsp;
<el-button type="text" @click="close">关闭</el-button>&nbsp;&nbsp;
<el-popover
placement="top-start"
title=""
width="400"
v-model="moreVisible"
trigger="manual" >
<el-row>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">产品编号:</font>
<el-input v-model="filters.id" style="width:100%;" placeholder="输入产品编号" @keyup.enter.native="searchXmProducts">
</el-input>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">创建时间:</font>
<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-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">
产品名称:
</font>
<el-input v-model="filters.key" style="width:100%;" placeholder="输入产品名字关键字">
</el-input>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">
产品经理:
</font>
<el-tag v-if="filters.pmUser" closable @click="selectFiltersPmUser" @close="clearFiltersPmUser()">{{filters.pmUser.username}}</el-tag>
<el-button v-else @click="selectFiltersPmUser()">选责任人</el-button>
<el-button @click="setFiltersPmUserAsMySelf()">我的</el-button>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<el-button type="text" @click="moreVisible=false" >关闭</el-button><el-button type="primary" @click="searchXmProducts" ></el-button>
</el-col>
</el-row>
<el-button type="text" slot="reference" @click="moreVisible=!moreVisible" style="float:right;">更多条件</el-button>
</el-popover>
</span>
</template>
<template slot-scope="scope">
<font>{{scope.row.productName}}</font>
</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>
<slot name="reference"><el-link title="产品,点击选择、清除选择" @click="productVisible=!productVisible" type="warning" slot="reference" icon="el-icon-search"><font style="font-size:14px;"><slot name="title">{{editForm && editForm.id?editForm.productName:'选择产品'}}</slot></font></el-link> </slot>
</el-popover>
<el-dialog v-if="dialog" append-to-body
v-model="productVisible">
<el-row >
<!--列表 XmProduct 产品表-->
<el-table ref="table" :height="maxTableHeight" :data="xmProducts" :row-class-name="tableRowClassName" @sort-change="sortChange" :highlight-current-row="true" current-row-key="id" v-loading="load.list" border @selection-change="selsChange" @row-click="rowClick" style="width: 100%;">
<el-table-column prop="productName" label="产品名称">
<template slot="header" slot-scope="scope">
产品名称
<span style="float:right;">
<el-button type="text" @click="clearSelect">清空</el-button>&nbsp;&nbsp;
<el-button type="text" @click="close">关闭</el-button>&nbsp;&nbsp;
<el-popover
placement="top-start"
title=""
width="400"
v-model="moreVisible"
trigger="manual" >
<el-row>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">产品编号:</font>
<el-input v-model="filters.id" style="width:100%;" placeholder="输入产品编号" @keyup.enter.native="searchXmProducts">
</el-input>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">创建时间:</font>
<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-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">
产品名称:
</font>
<el-input v-model="filters.key" style="width:100%;" placeholder="输入产品名字关键字">
</el-input>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">
产品经理:
</font>
<el-tag v-if="filters.pmUser" closable @click="selectFiltersPmUser" @close="clearFiltersPmUser()">{{filters.pmUser.username}}</el-tag>
<el-button v-else @click="selectFiltersPmUser()">选责任人</el-button>
<el-button @click="setFiltersPmUserAsMySelf()">我的</el-button>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<el-button type="text" @click="moreVisible=false" >关闭</el-button><el-button type="primary" @click="searchXmProducts" ></el-button>
</el-col>
</el-row>
<el-button type="text" slot="reference" @click="moreVisible=!moreVisible" style="float:right;">更多条件</el-button>
</el-popover>
</span>
</template>
<template slot-scope="scope">
<font>{{scope.row.productName}}</font>
</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>
</el-dialog>
</section>
</template>
<script>
import util from '@/common/js/util';//
//import Sticky from '@/components/Sticky' // header
//import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmProductWithState } from '@/api/xm/core/xmProduct';
import { mapGetters } from 'vuex'
import UsersSelect from "@/views/mdp/sys/user/UsersSelect";
const map=new Map();
export default {
props:['dialog','linkProjectId','iterationId','autoSelect'],
computed: {
...mapGetters([
'userInfo','roles'
])
},
watch:{
iterationId(){
this.initData();
},
linkProjectId(){
this.initData();
}
},
data() {
const beginDate = new Date();
const endDate = new Date();
beginDate.setTime(beginDate.getTime() - 3600 * 1000 * 24 * 7 * 4 * 12 );
return {
filters: {
key: '',
id:'',//
pmUser:null,//
},
xmProducts: [],//
pageInfo:{//
total:0,//0>0
pageSize:10,//
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:{},// params=[{categoryId:'0001',itemCode:'sex'}] {'sex':[{optionValue:'1',optionName:'',seqOrder:'1',fp:'',isDefault:'0'},{optionValue:'2',optionName:'',seqOrder:'2',fp:'',isDefault:'0'}]}
//xmProduct
addForm: {
id:'',productName:'',branchId:'',remark:''
},
//xmProduct
editForm: {
id:'',productName:'',branchId:'',remark:''
},
selectFiltersPmUserVisible:false,
maxTableHeight:300,
dateRanger: [ ],
pickerOptions: util.pickerOptions('datarange'),
productVisible:false,
moreVisible:false,
/**begin 自定义属性请在下面加 请加备注**/
/**end 自定义属性请在上面加 请加备注**/
}
},//end data
methods: {
handleSizeChange(pageSize) {
this.pageInfo.pageSize=pageSize;
this.getXmProducts();
},
handleCurrentChange(pageNum) {
this.pageInfo.pageNum = pageNum;
this.getXmProducts();
},
// 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.getXmProducts();
},
searchXmProducts(){
this.pageInfo.count=true;
this.getXmProducts();
},
// XmProduct
getXmProducts() {
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(",")
}
if(this.filters.key!==""){
params.key="%"+this.filters.key+"%"
}
if(this.linkProjectId){
params.projectId=this.linkProjectId
}
if(this.iterationId){
params.iterationId=this.iterationId
}
if(this.filters.id){
params.id=this.filters.id
}
if(this.filters.pmUser){
params.pmUserid=this.filters.pmUser.userid
}
this.load.list = true;
listXmProductWithState(params).then((res) => {
var tips=res.data.tips;
if(tips.isOk){
this.pageInfo.total = res.data.total;
this.pageInfo.count=false;
this.xmProducts = res.data.data;
if(this.iterationId){
map.set(this.iterationId,this.xmProducts)
}else if(this.linkProjectId){
map.set(this.linkProjectId,this.xmProducts)
}
if(this.autoSelect!==false&&this.xmProducts.length>0 && this.productVisible==false){
var row=this.xmProducts[0];
this.$refs.table.setCurrentRow(row);
this.rowClick(row);
}
}else{
this.$notify({showClose: true, message: tips.msg, type: 'error' });
}
this.load.list = false;
}).catch( err => this.load.list = false );
},
//xmProduct
selsChange: function (sels) {
this.sels = sels;
},
rowClick: function(row, event, column){
this.editForm=row
this.$emit('row-click',row, event, column);// @row-click="rowClick"
this.selectedProduct(row)
this.productVisible=false;
this.moreVisible=false;
},
selectedProduct:function(row){
this.editForm=row
this.$emit('selected',row);
this.productVisible=false;
this.moreVisible=false;
},
/**begin 自定义函数请在下面加**/
clearFiltersPmUser:function(){
this.filters.pmUser=null;
this.searchXmProducts();
},
selectFiltersPmUser(){
this.selectFiltersPmUserVisible=true;
},
onFiltersPmUserSelected(users){
if(users && users.length>0){
this.filters.pmUser=users[0]
}else{
this.filters.pmUser=null;
}
this.selectFiltersPmUserVisible=false;
this.searchXmProducts();
},
setFiltersPmUserAsMySelf(){
this.filters.pmUser=this.userInfo;
this.searchXmProducts();
},
tableRowClassName({row, rowIndex}) {
if (row.id == this.editForm.id) {
return 'success-row';
}
return '';
},
clearSelect(){
this.$refs.table.setCurrentRow();
this.$emit("clear-select");
this.selectedProduct(null);
this.productVisible=false;
this.moreVisible=false;
},
close(){
this.productVisible=false;
this.moreVisible=false;
this.$emit("close");
},
initData(){
if(this.iterationId){
var xmProducts=map.get(this.iterationId);
if(xmProducts){
this.xmProducts=xmProducts;
if(this.productVisible==false){
if(this.autoSelect!==false && this.xmProducts.length>0){
var row=this.xmProducts[0];
this.$refs.table.setCurrentRow(row);
this.rowClick(row);
}
}
}else{
this.searchXmProducts();
}
}else if(this.linkProjectId){
var xmProducts=map.get(this.linkProjectId);
if(xmProducts){
this.xmProducts=xmProducts;
if(this.productVisible==false){
if(this.autoSelect!==false && this.xmProducts.length>0){
var row=this.xmProducts[0];
this.$refs.table.setCurrentRow(row);
this.rowClick(row);
}
}
}else{
this.searchXmProducts();
}
}else{
this.searchXmProducts();
}
},
},//end methods
components: {
UsersSelect,
//
},
mounted() {
this.$nextTick(() => {
this.maxTableHeight = util.calcTableMaxHeight(this.$refs.table.$el);
this.initData();
});
}
}
</script>
<style scoped>
.more-label-font{
text-align:center;
float:left;
padding-top:5px;
}
.align-right{
float: right;
}
</style>

357
src/views/xm/core/components/XmProjectSelect.vue

@ -0,0 +1,357 @@
<template>
<section>
<el-popover
placement="bottom"
width="400"
trigger="manual"
v-model="projectVisible">
<el-row >
<!--列表 XmProject 项目表-->
<el-table ref="table" :height="maxTableHeight" :data="xmProjects" :row-class-name="tableRowClassName" @sort-change="sortChange" :highlight-current-row="true" current-row-key="id" v-loading="load.list" border @selection-change="selsChange" @row-click="rowClick" style="width: 100%;">
<el-table-column prop="name" label="项目名称">
<template slot="header" slot-scope="scope">
项目名称
<span style="float:right;">
<el-button type="text" @click="clearSelect">清空</el-button>&nbsp;&nbsp;
<el-button type="text" @click="close">关闭</el-button>&nbsp;&nbsp;
<el-popover
placement="top-start"
title=""
width="400"
v-model="moreVisible"
trigger="manual" >
<el-row>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">项目编号:</font>
<el-input v-model="filters.id" style="width:100%;" placeholder="输入项目编号" @keyup.enter.native="searchXmProjects">
</el-input>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">创建时间:</font>
<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-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">
项目名称:
</font>
<el-input v-model="filters.key" style="width:100%;" placeholder="输入项目名字关键字">
</el-input>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">
项目经理:
</font>
<el-tag v-if="filters.pmUser" closable @click="selectFiltersPmUser" @close="clearFiltersPmUser()">{{filters.pmUser.username}}</el-tag>
<el-button v-else @click="selectFiltersPmUser()">选责任人</el-button>
<el-button @click="setFiltersPmUserAsMySelf()">我的</el-button>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<el-button type="text" @click="moreVisible=false" >关闭</el-button><el-button type="primary" @click="searchXmProjects" ></el-button>
</el-col>
</el-row>
<el-button type="text" slot="reference" @click="moreVisible=!moreVisible" style="float:right;">更多条件</el-button>
</el-popover>
</span>
</template>
<template slot-scope="scope">
<font>{{scope.row.name}}</font>
</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>
<span slot="reference" @click="projectVisible=!projectVisible">
<slot name="reference"><el-link title="项目,点击选择、清除选择" type="warning" icon="el-icon-search"><font style="font-size:14px;"><slot name="title">{{editForm && editForm.id?editForm.name:'选择项目'}}</slot></font></el-link> </slot>
</span>
</el-popover>
<el-drawer title="选择员工" :visible.sync="selectFiltersPmUserVisible" size="60%" append-to-body>
<users-select @confirm="onFiltersPmUserSelected" ref="usersSelect"></users-select>
</el-drawer>
</section>
</template>
<script>
import util from '@/common/js/util';//
//import Sticky from '@/components/Sticky' // header
//import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmProject } from '@/api/xm/core/xmProject';
import { mapGetters } from 'vuex'
import UsersSelect from "@/views/mdp/sys/user/UsersSelect";
const map=new Map();
export default {
props:['linkProductId','linkIterationId','autoSelect'],
computed: {
...mapGetters([
'userInfo','roles'
])
},
watch:{
linkIterationId(){
this.initData();
},
linkProductId(){
this.initData();
}
},
data() {
const beginDate = new Date();
const endDate = new Date();
beginDate.setTime(beginDate.getTime() - 3600 * 1000 * 24 * 7 * 4 * 12 );
return {
filters: {
key: '',
id:'',//
pmUser:null,//
},
xmProjects: [],//
pageInfo:{//
total:0,//0>0
pageSize:10,//
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:{},// params=[{categoryId:'0001',itemCode:'sex'}] {'sex':[{optionValue:'1',optionName:'',seqOrder:'1',fp:'',isDefault:'0'},{optionValue:'2',optionName:'',seqOrder:'2',fp:'',isDefault:'0'}]}
//xmProject
addForm: {
id:'',name:'',branchId:'',remark:''
},
//xmProject
editForm: {
id:'',name:'',branchId:'',remark:''
},
selectFiltersPmUserVisible:false,
maxTableHeight:300,
dateRanger: [ ],
pickerOptions: util.pickerOptions('datarange'),
projectVisible:false,
moreVisible:false,
/**begin 自定义属性请在下面加 请加备注**/
/**end 自定义属性请在上面加 请加备注**/
}
},//end data
methods: {
handleSizeChange(pageSize) {
this.pageInfo.pageSize=pageSize;
this.getXmProjects();
},
handleCurrentChange(pageNum) {
this.pageInfo.pageNum = pageNum;
this.getXmProjects();
},
// 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.getXmProjects();
},
searchXmProjects(){
this.pageInfo.count=true;
this.getXmProjects();
},
// XmProject
getXmProjects() {
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(",")
}
if(this.filters.key!==""){
params.key="%"+this.filters.key+"%"
}
if(this.linkProductId){
params.linkProductId=this.linkProductId
}
if(this.linkIterationId){
params.linkIterationId=this.linkIterationId
}
if(this.filters.id){
params.id=this.filters.id
}
if(this.filters.pmUser){
params.pmUserid=this.filters.pmUser.userid
}
this.load.list = true;
listXmProject(params).then((res) => {
var tips=res.data.tips;
if(tips.isOk){
this.pageInfo.total = res.data.total;
this.pageInfo.count=false;
this.xmProjects = res.data.data;
if(this.linkIterationId){
map.set(this.linkIterationId,this.xmProjects)
}else if(this.linkProductId){
map.set(this.linkProductId,this.xmProjects)
}
if(this.autoSelect!==false&&this.xmProjects.length>0 && this.projectVisible==false){
var row=this.xmProjects[0];
this.$refs.table.setCurrentRow(row);
this.rowClick(row);
}
}else{
this.$notify({showClose: true, message: tips.msg, type: 'error' });
}
this.load.list = false;
}).catch( err => this.load.list = false );
},
//xmProject
selsChange: function (sels) {
this.sels = sels;
},
rowClick: function(row, event, column){
this.editForm=row
this.$emit('row-click',row, event, column);// @row-click="rowClick"
this.selectedProduct(row)
this.projectVisible=false;
this.moreVisible=false;
},
selectedProduct:function(row){
this.editForm=row
this.$emit('selected',row);
this.projectVisible=false;
this.moreVisible=false;
},
/**begin 自定义函数请在下面加**/
clearFiltersPmUser:function(){
this.filters.pmUser=null;
this.searchXmProjects();
},
selectFiltersPmUser(){
this.selectFiltersPmUserVisible=true;
},
onFiltersPmUserSelected(users){
if(users && users.length>0){
this.filters.pmUser=users[0]
}else{
this.filters.pmUser=null;
}
this.selectFiltersPmUserVisible=false;
this.searchXmProjects();
},
setFiltersPmUserAsMySelf(){
this.filters.pmUser=this.userInfo;
this.searchXmProjects();
},
tableRowClassName({row, rowIndex}) {
if (row.id == this.editForm.id) {
return 'success-row';
}
return '';
},
clearSelect(){
this.$refs.table.setCurrentRow();
this.$emit("clear-select");
this.selectedProduct(null);
this.projectVisible=false;
this.moreVisible=false;
},
close(){
this.projectVisible=false;
this.moreVisible=false;
this.$emit("close");
},
initData(){
if(this.linkIterationId){
var xmProjects=map.get(this.linkIterationId);
if(xmProjects){
this.xmProjects=xmProjects;
if(this.projectVisible==false){
if(this.autoSelect!==false && this.xmProjects.length>0){
var row=this.xmProjects[0];
this.$refs.table.setCurrentRow(row);
this.rowClick(row);
}
}
}else{
this.searchXmProjects();
}
}else if(this.linkProductId){
var xmProjects=map.get(this.linkProductId);
if(xmProjects){
this.xmProjects=xmProjects;
if(this.projectVisible==false){
if(this.autoSelect!==false && this.xmProjects.length>0){
var row=this.xmProjects[0];
this.$refs.table.setCurrentRow(row);
this.rowClick(row);
}
}
}else{
this.searchXmProjects();
}
}else{
this.searchXmProjects();
}
},
},//end methods
components: {
UsersSelect,
//
},
mounted() {
this.$nextTick(() => {
this.maxTableHeight = util.calcTableMaxHeight(this.$refs.table.$el);
this.initData();
});
}
}
</script>
<style scoped>
.more-label-font{
text-align:center;
float:left;
padding-top:5px;
}
.align-right{
float: right;
}
</style>

98
src/views/xm/core/components/XmTableConfig.vue

@ -0,0 +1,98 @@
<template>
<section>
<el-popover
placement="bottom"
width="500"
v-model="formVisible"
trigger="manual" > <el-form :model="editForm" label-width="100px" ref="editForm">
<el-form-item :label="item.label" :prop="item.property" v-for="(item,index) in columnsConfig" :key="index">
<el-checkbox v-model="item.isShow" @change="onCheckboxChange(item,$event)">是否显示</el-checkbox>
</el-form-item>
<el-form-item label="" class="padding">
<el-button type="text" @click="cancel">关闭</el-button>
<el-button :disabled="editForm.calcType!=='2' && editForm.ntype==='1'" type="primary" @click="submit">确认</el-button>
</el-form-item>
</el-form>
<el-button title="点击修改表格配置" @click="showConfig" slot="reference" icon="el-icon-setting"><font style="font-size:14px;"></font></el-button>
</el-popover>
</section>
</template>
<script>
import util from '@/common/js/util';//
import config from '@/common/config';//
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters([
'userInfo','roles'
]),
},
props:['table'],
watch:{
},
data() {
return {
columnsConfig:[],
editForm:{},
formVisible:false,
}
},//end data
methods: {
cancel(){
this.formVisible=false;
this.$emit("cancel")
},
submit(){
this.$emit("submit");
this.formVisible=false;
},
showConfig(){
if(this.columnsConfig.length>0){
this.formVisible=true;
return;
}
if(this.table){
var columns=this.table.$children.filter(i=>i.columnConfig&&i.columnConfig.label)
columns=columns.map((column)=>{
if(column && column.columnConfig){
return {
label:column.columnConfig.label,
property:column.columnConfig.property,
isShow:true,
id:column.columnConfig.id,
}
}
});
this.columnsConfig=columns
this.formVisible=true;
}
},
onCheckboxChange(column,newVal){
var doc=this.table.$el;
var eles=doc.querySelectorAll("."+column.id);
eles.forEach(i=>{
i.style.display=newVal?"":"none";
})
this.table.doLayout();
}
},//end methods
components: {
//
},
mounted() {
}
}
</script>
<style lang="scss" scoped>
</style>

66
src/views/xm/core/xmGroup/XmGroupDialog.vue

@ -0,0 +1,66 @@
<template>
<section>
<el-drawer title="选择组员" :visible.sync="visible" show-close append-to-body size="50%" @close="option=null">
<xm-group-select :xm-product="xmProduct" :sel-project="selProject" :isSelectSingleUser="isSelectSingleUser" :visible="visible" @user-confirm="onUserConfirm"></xm-group-select>
</el-drawer>
</section>
</template>
<script>
import util from '@/common/js/util'; //
import {
mapGetters
} from 'vuex'
import XmGroupSelect from "./XmGroupSelect.vue"
export default {
name:"tagDialog",
computed: {
...mapGetters([
'workShop', 'userInfo'
])
},
//
props: ['selProject', 'xmProduct','isSelectSingleUser'],
watch: {
},
data() {
return {
visible:false,
option:null/**{data:'',action:''} */,
}
}, //end data
methods: {
open(option){
this.visible=true;
this.option=option;
},
close(){
this.visible=false;
this.option=null;
},
/**
* @select-confirm
*
*
*/
onUserConfirm(users){
this.$emit('user-confirm',users,{...this.option})
this.visible=false;
this.option=null;
}
}, //end methods
components: {
XmGroupSelect,
},
mounted() {
}
}
</script>
<style scoped>
</style>

22
src/views/xm/core/xmGroup/XmGroupMng.vue

@ -1,14 +1,8 @@
<template>
<section class="page-container border padding" >
<el-row>
<xm-project-select style="display:inline;" v-if="!selProject &&pgClass==='0'" :auto-select="false" :link-iteration-id="xmIteration?xmIteration.id:null" :link-product-id="xmProduct?xmProduct.id:null" @row-click="onProjectRowClick" @clear-select="onProjectClearSelect"></xm-project-select>
<el-popover v-if="pgClass==='0' && (!selProject || !selProject.id)"
placement="bottom"
width="400"
trigger="click">
<xm-project-select :auto-select="true" :xm-iteration="xmIteration" :xm-product="xmProduct" @row-click="onProjectRowClick" @clear-select="onProjectClearSelect"></xm-project-select>
<el-link type="warning" slot="reference" icon="el-icon-search"><font style="font-size:14px;">{{filters.selProject?filters.selProject.name:'选择项目'}}</font></el-link>
</el-popover>
<el-input v-model="filters.key" style="width:15%;" clearable placeholder="名称过滤"></el-input>
<el-button type="primary" @click="searchXmGroups" icon="el-icon-search">刷新</el-button>
<el-button type="plain" @click="showGroupState" icon="el-icon-s-data">小组进度</el-button>
@ -188,16 +182,9 @@
<el-drawer v-else-if="!selProject && xmProduct" :title="xmProduct.productName+'小组进度数据查看'" center :visible.sync="xmGroupStateVisible" size="80%" :close-on-click-modal="false" append-to-body>
<xm-group-state-mng :xm-product="xmProduct" :visible="xmGroupStateVisible" ></xm-group-state-mng>
</el-drawer>
<el-drawer v-if="currNodeType=='group'&&editForm.groupName" center :title="(editForm==null?editForm.groupName:'')+'小组成员管理'" :visible.sync="groupUserVisible" size="80%" :close-on-click-modal="false" append-to-body>
<xm-group-user-mng :xm-group="editForm" :visible="groupUserVisible" ></xm-group-user-mng>
</el-drawer>
<el-drawer title="选中项目" :visible.sync="selectProjectVisible" size="80%" append-to-body :close-on-click-modal="false">
<xm-project-list @project-confirm="onPorjectConfirm"></xm-project-list>
</el-drawer>
<el-drawer title="选中产品" :visible.sync="selectProductVisible" size="80%" append-to-body :close-on-click-modal="false">
<xm-product-select :isSelectProduct="true" @selected="onProductConfirm"></xm-product-select>
</el-drawer>
</el-row>
</section>
@ -222,15 +209,14 @@
import UsersSelect from "@/views/mdp/sys/user/UsersSelect";
import XmGroupStateMng from '../xmGroupState/XmGroupStateMng';//
import XmGroupUserMng from '../xmGroupUser/XmGroupUserMng';//
import XmProjectList from '../xmProject/XmProjectList';
import XmProjectSelect from '../xmProject/XmProjectSelect';
import XmProductSelect from '../xmProduct/XmProductSelect.vue';
import XmProjectSelect from '@/views/xm/core/components/XmProjectSelect';
import XmProductSelect from '@/views/xm/core/components/XmProductSelect.vue'
export default {
name:'xmGroupMng',
components: {
XmGroupEdit,VueOkrTree,UsersSelect,XmGroupStateMng,XmGroupUserMng,XmProjectList,
XmGroupEdit,VueOkrTree,UsersSelect,XmGroupStateMng,XmGroupUserMng,
XmProductSelect,XmProjectSelect,
},
props:["visible","selProject" ,"isSelectSingleUser","isSelectMultiUser",'xmProduct','xmIteration','pgClass'],

32
src/views/xm/core/xmGroup/XmGroupSelect.vue

@ -1,20 +1,11 @@
<template>
<section class="border padding-left">
<el-row class="padding-top">
<el-popover v-if="(pgClass==='0'||!pgClass) && (!selProject || !selProject.id)"
placement="bottom"
width="400"
trigger="click">
<xm-project-select :auto-select="true" :xm-product="xmProduct" @row-click="onProjectRowClick" @clear-select="onProjectClose"></xm-project-select>
<el-link type="warning" slot="reference" icon="el-icon-search"><font style="font-size:14px;">{{filters.selProject?filters.selProject.name:'选择项目'}}</font></el-link>
</el-popover>
<el-popover v-if="pgClass==='1' && (!xmProduct || !xmProduct.id)"
placement="bottom"
width="400"
trigger="click">
<xm-product-select :auto-select="true" :sel-project="selProject" @row-click="onProductRowClick" @clear-select="onProductClose"></xm-product-select>
<el-link type="warning" slot="reference" icon="el-icon-search"><font style="font-size:14px;">{{filters.xmProduct?filters.xmProduct.productName:'选择项目'}}</font></el-link>
</el-popover>
<xm-project-select style="display:inline;" v-if="!selProject" :auto-select="false" :xm-product="xmProduct" @row-click="onProjectRowClick" @clear-select="onProjectClose"></xm-project-select>
<xm-product-select style="display:inline;" v-if="!xmProduct" :auto-select="false" :link-project-id="selProject?selProject.id:null" @row-click="onProductRowClick" @clear-select="onProductClose"></xm-product-select>
<el-button type="primary" @click="userConfirm" icon="el-icon-finished">确认选择</el-button>
</el-row>
<el-row class="padding-top" v-loading="load.list" :style="{overflowX:'auto',height:maxTableHeight+'px'}" ref="table">
@ -30,15 +21,6 @@
</el-col>
</el-row>
</el-row>
<el-drawer title="选中项目团队" :visible.sync="selectProjectVisible" size="80%" append-to-body :close-on-click-modal="false">
<xm-project-list @project-confirm="onProjectRowClick"></xm-project-list>
</el-drawer>
<el-drawer title="选中产品团队" :visible.sync="selectProductVisible" size="80%" append-to-body :close-on-click-modal="false">
<xm-product-select :isSelectProduct="true" @selected="onProductRowClick"></xm-product-select>
</el-drawer>
</section>
</template>
@ -47,10 +29,10 @@
//import Sticky from '@/components/Sticky' // header
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { getGroups } from '@/api/xm/core/xmGroup';
import XmProjectSelect from '../xmProject/XmProjectSelect';
import XmProjectSelect from '@/views/xm/core/components/XmProjectSelect';
import {mapGetters} from 'vuex'
import XmProductSelect from '../xmProduct/XmProductSelect.vue';
import XmProductSelect from '@/views/xm/core/components/XmProductSelect.vue'
export default {
computed: {

12
src/views/xm/core/xmIteration/XmIterationAdd.vue

@ -4,14 +4,8 @@
<!--新增界面 XmIteration 迭代定义-->
<el-form :model="addForm" label-width="120px" :rules="addFormRules" ref="addForm">
<el-form-item label="归属产品" prop="productId">
<el-popover v-if="!xmProduct||!xmProduct.id"
placement="bottom"
width="400"
v-model="productSelectVisible"
trigger="manual">
<xm-product-select ref="xmProductSelect" :auto-select="true" :sel-project="selProject" @row-click="onProductRowClick" @clear-select="onProductClearSelect" @close="productSelectVisible=false"></xm-product-select>
<el-link type="warning" @click="productSelectVisible=true" slot="reference" icon="el-icon-search"><font style="font-size:14px;">{{addForm.productId?addForm.productName:'选择产品'}}</font></el-link>
</el-popover>
<xm-product-select v-if="!xmProduct||!xmProduct.id" ref="xmProductSelect" :auto-select="true" :sel-project="selProject" @row-click="onProductRowClick" @clear-select="onProductClearSelect" @close="productSelectVisible=false"></xm-product-select>
<span v-else>{{addForm.productName}}</span>
</el-form-item>
<el-form-item label="迭代名称" prop="iterationName">
@ -55,7 +49,7 @@
import { mapGetters } from 'vuex'
import UsersSelect from "@/views/mdp/sys/user/UsersSelect";
import XmProductSelect from '../xmProduct/XmProductSelect.vue';
import XmProductSelect from '@/views/xm/core/components/XmProductSelect.vue'
export default {
computed: {

3
src/views/xm/core/xmIteration/XmIterationEdit.vue

@ -10,6 +10,9 @@
</el-step>
</el-steps>
</el-row>
<el-row style="padding-left:70px;">
<font color="blue" style="text-align:center;">注意请尽量在评审会阶段把需求明确进入计划会后不允许再添加需求进入迭代原则上需求评审后需求只出不进</font>
</el-row>
<el-row>
<!--新增界面 XmIteration 迭代定义-->
<el-form :model="editForm" label-width="120px" :rules="editFormRules" ref="editForm">

11
src/views/xm/core/xmIteration/XmIterationForLinkComplex.vue

@ -5,13 +5,8 @@
<el-tabs type="border-card" :value="showPanel" @tab-click="tabClick">
<el-tab-pane lazy name="iterations" disabled>
<div slot="label">
<el-popover
placement="bottom"
width="400"
trigger="click">
<xm-iteration-select ref="xmIterationSelect" :auto-select="true" :sel-project="selProject" :product-id="xmProduct?xmProduct.id:null" @row-click="onIterationRowClick" @clear-select="onIterationClearSelect"></xm-iteration-select>
<el-link type="warning" slot="reference" icon="el-icon-search"><font style="font-size:14px;">{{xmIteration?xmIteration.iterationName:'选择迭代'}}</font></el-link>
</el-popover>
<xm-iteration-select ref="xmIterationSelect" :auto-select="true" :link-project-id="selProject?selProject.id:null" :product-id="xmProduct?xmProduct.id:null" @row-click="onIterationRowClick" @clear="onIterationClearSelect"></xm-iteration-select>
</div>
</el-tab-pane>
@ -64,7 +59,7 @@
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { delXmIterationLink } from '@/api/xm/core/xmIterationLink';
import XmIterationSelect from './XmIterationSelect.vue'
import XmIterationSelect from '@/views/xm/core/components/XmIterationSelect.vue'
import XmMenuMng from '../xmMenu/XmMenuMng.vue'
import XmIterationStateShow from '../xmIterationState/XmIterationStateShow.vue'
import { mapGetters } from 'vuex'

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

@ -51,9 +51,6 @@
import util from '@/common/js/util';//
//import Sticky from '@/components/Sticky' // header
//import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmProject,editStatus , delXmProject, batchDelXmProject } from '@/api/xm/core/xmProject';
import XmProjectAdd from '../xmProject/XmProjectAdd';//
import XmProjectEdit from '../xmProject/XmProjectEdit';//
import { mapGetters } from 'vuex';
import xmTaskMng from '../xmTask/XmTaskMng';
import xmGroupMng from '../xmGroup/XmGroupMng';

49
src/views/xm/core/xmIteration/XmIterationMng.vue

@ -141,7 +141,7 @@
import XmGantt from '../components/xm-gantt';
import { mapGetters } from 'vuex'
import XmIterationSelect from './XmIterationSelect.vue';
import XmIterationSelect from '@/views/xm/core/components/XmIterationSelect.vue';
export default {
computed: {
@ -150,8 +150,8 @@ import XmIterationSelect from './XmIterationSelect.vue';
]),
xmIterationTreeData(){
return this.translateDataToTree(this.xmIterations);
},
return this.xmIterations
},
},
props:['xmProduct','selProject','menuId','visible'],
watch:{
@ -408,49 +408,6 @@ import XmIterationSelect from './XmIterationSelect.vue';
this.editForm=row
this.$emit('row-click',row, event, column);// @row-click="rowClick"
},
/**begin 自定义函数请在下面加**/
translateDataToTree(data2) {
var data=JSON.parse(JSON.stringify(data2));
let parents = data.filter(value =>{
//
if(value.pid == 'undefined' || value.pid == null || value.pid == ''){
return true;
//
}else if(data.some(i=>value.pid==i.id)){
return false;
}else {
return true
}
})
let children = data.filter(value =>{
if(data.some(i=>value.pid==i.id)){
return true;
}else{
return false;
}
})
let translator = (parents, children) => {
parents.forEach((parent) => {
children.forEach((current, index) => {
if (current.pid === 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
},
clearSelectIteration(){
this.editForm=this.editFormInit

384
src/views/xm/core/xmIteration/XmIterationSelect.vue

@ -1,384 +0,0 @@
<template>
<section>
<el-row>
<!--列表 XmIteration 迭代定义-->
<el-table ref="table" :height="maxTableHeight" :data="xmIterationTreeData" row-key="id" default-expand-all :tree-props="{children: 'children', hasChildren: 'hasChildren'}" @sort-change="sortChange" highlight-current-row v-loading="load.list" border @selection-change="selsChange" @row-click="rowClick" style="width: 100%;">
<el-table-column type="index" label="序号" ></el-table-column>
<el-table-column prop="iterationName" label="迭代名称" >
<template slot="header" slot-scope="scope">
迭代名称 <el-button type="text" @click="clearSelectIteration">清空所选</el-button> &nbsp;<el-button type="text" @click="close">关闭</el-button>
<el-popover v-if=" !menuId && !productId"
placement="top-start"
title=""
width="400"
trigger="hover" >
<el-row>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">
迭代查询范围
</font>
<el-select v-model="filters.queryScope" style="width:100%;" placeholder="迭代查询范围">
<el-option :label="userInfo.branchName+'机构下所有的迭代'" value="branchId"></el-option>
<el-option label="我相关的迭代" value="compete"></el-option>
<el-option label="按迭代编号精确查找" value="iterationId"></el-option>
<el-option label="后台智能匹配" value=""></el-option>
</el-select>
</el-col>
<el-col v-if="filters.queryScope=='iterationId'" :span="24" style="padding-top:5px;">
<el-input v-model="filters.id" style="width:100%;" placeholder="输入迭代编号" @keyup.enter.native="searchXmProducts">
</el-input>
</el-col>
<el-col v-if="filters.queryScope!='iterationId'" :span="24" style="padding-top:5px;">
<font class="more-label-font">上线时间:</font>
<el-date-picker
v-model="dateRangerOnline"
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-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">迭代名称:</font><el-input v-model="filters.key" style="width: 60%;" placeholder="模糊查询"></el-input>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<el-tag>默认只能查询本人创建的迭代本人作为需求责任人参与的迭代</el-tag>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<el-button type="primary" icon="el-icon-search" @click="getXmIterations">查询</el-button>
</el-col>
</el-row>
<el-button type="text" slot="reference" style="float:right;">更多条件</el-button>
</el-popover>
</template>
<template slot-scope="scope">
{{scope.row.iterationName}} <font :color="calcFinishRate(scope.row)==100?'green':'#FF8C00'">{{calcFinishRate(scope.row)}}%</font>
</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 config from '@/common/config';//
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmIteration,listXmIterationWithState, delXmIteration, batchDelXmIteration,loadTasksToXmIterationState } from '@/api/xm/core/xmIteration';
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters([
'userInfo','roles'
]),
xmIterationTreeData(){
return this.translateDataToTree(this.xmIterations);
},
},
props:[ 'productId','menuId','visible','selProject','autoSelect'],
watch:{
visible:function(visible){
if(visible==true){
this.clearSelectIteration();
this.getXmIterations();
}
},
productId:function(){
this.getXmIterations();
}
},
data() {
const beginDate = new Date();
const endDate = new Date();
beginDate.setTime(beginDate.getTime() - 3600 * 1000 * 24 * 7 * 4 * 12 );
endDate.setTime(endDate.getTime() + 3600 * 1000 * 24 * 7 * 4 * 12 );
return {
filters: {
key: '',
queryScope:'',// iterationId\branchId\compete\''
id:'',//
},
pickerOptions: util.pickerOptions('datarange'),
dateRangerOnline: [
],//线
xmIterations: [],//
pageInfo:{//
total:0,//0>0
pageSize:10,//
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:{
//sex:[],
},// params=[{categoryId:'0001',itemCode:'sex'}] {'sex':[{optionValue:'1',optionName:'',seqOrder:'1',fp:'',isDefault:'0'},{optionValue:'2',optionName:'',seqOrder:'2',fp:'',isDefault:'0'}]}
addFormVisible: false,//xmIteration
//xmIteration
addForm: {
id:'',branchId:'',iterationName:'',startTime:'',endTime:'',onlineTime:'',pid:'',adminUserid:'',adminUsername:'',ctime:'',budgetCost:'',budgetWorkload:'',distBudgetCost:'',distBudgetWorkload:'',actCost:'',actWorkload:'',actStaffNum:'',seqNo:'',
},
editFormVisible: false,//
//xmIteration
editForm: {
id:'',branchId:'',iterationName:'',startTime:'',endTime:'',onlineTime:'',pid:'',adminUserid:'',adminUsername:'',ctime:'',budgetCost:'',budgetWorkload:'',distBudgetCost:'',distBudgetWorkload:'',actCost:'',actWorkload:'',actStaffNum:'',seqNo:'',
},
editFormInit: {
id:'',branchId:'',iterationName:'',startTime:'',endTime:'',onlineTime:'',pid:'',adminUserid:'',adminUsername:'',ctime:'',budgetCost:'',budgetWorkload:'',distBudgetCost:'',distBudgetWorkload:'',actCost:'',actWorkload:'',actStaffNum:'',seqNo:'',
},
/**begin 自定义属性请在下面加 请加备注**/
valueChangeRows:[],
parentIteration:null,
iterationStateVisible:false,
gstcVisible:false,
maxTableHeight:300,
ganrrColumns: {
children: 'children',
name: 'iterationName',
id: 'id',
pid: 'pid',
startDate: 'startTime',
endDate: 'endTime',
}
/**end 自定义属性请在上面加 请加备注**/
}
},//end data
methods: {
handleSizeChange(pageSize) {
this.pageInfo.pageSize=pageSize;
this.getXmIterations();
},
handleCurrentChange(pageNum) {
this.pageInfo.pageNum = pageNum;
this.getXmIterations();
},
// 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.getXmIterations();
},
searchXmIterations(){
this.pageInfo.count=true;
this.getXmIterations();
},
// XmIteration
getXmIterations() {
debugger;
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(",")
}
if(this.filters.key){
params.key= "%"+this.filters.key+"%"
}
if(this.productId){
params.productId=this.productId
}
if(this.menuId){
params.menuId=this.menuId
}
if( !this.menuId && !this.productId ){
params.queryScope=this.filters.queryScope
if(this.filters.queryScope=='iterationId'){
if(!this.filters.id){
this.$notify({showClose: true, message:"您选择了按迭代编号精确查找模式,请输入迭代编号", type: 'error' });
return;
}
params.id=this.filters.id
}
if(this.filters.queryScope=="branchId"){
params.branchId=this.userInfo.branchId
}
}
if(this.selProject && this.selProject.id){
params.projectId=this.selProject.id
}
if(this.dateRangerOnline && this.dateRangerOnline.length==2){
params.onlineTimeStart=this.dateRangerOnline[0]
params.onlineTimeEnd=this.dateRangerOnline[1]
}
this.load.list = true;
listXmIterationWithState(params).then((res) => {
var tips=res.data.tips;
if(tips.isOk){
this.pageInfo.total = res.data.total;
this.pageInfo.count=false;
this.xmIterations = res.data.data;
if(this.autoSelect===true&&this.xmIterations.length>0){
var row=this.xmIterations[0];
this.$refs.table.setCurrentRow(row);
this.rowClick(row);
}
}else{
this.$notify({showClose: true, message: tips.msg, type: 'error' });
}
this.load.list = false;
}).catch( err => this.load.list = false );
},
//xmIteration
selsChange: function (sels) {
this.sels = sels;
},
rowClick: function(row, event, column){
this.editForm=row
this.$emit('row-click',row, event, column);// @row-click="rowClick"
},
/**begin 自定义函数请在下面加**/
translateDataToTree(data2) {
var data=JSON.parse(JSON.stringify(data2));
let parents = data.filter(value =>{
//
if(value.pid == 'undefined' || value.pid == null || value.pid == ''){
return true;
//
}else if(data.some(i=>value.pid==i.id)){
return false;
}else {
return true
}
})
let children = data.filter(value =>{
if(data.some(i=>value.pid==i.id)){
return true;
}else{
return false;
}
})
let translator = (parents, children) => {
parents.forEach((parent) => {
children.forEach((current, index) => {
if (current.pid === 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
},
clearSelectIteration(){
this.editForm=this.editFormInit
this.$refs.table.setCurrentRow();
this.$emit('clear-select',null );// @row-click="rowClick"
},
fieldChange:function(row,fieldName){
if(this.valueChangeRows.some(i=>i.id==row.id)){
return;
}else{
this.valueChangeRows.push(row)
}
},
formatterDate(row,column,cellValue, index){
if(cellValue){
return cellValue.substr(0,10);
}else{
return cellValue;
}
},
/**end 自定义函数请在上面加**/
calcFinishRate(row){
if(row.finishRate){
return parseInt(row.finishRate);
}else{
return 0;
}
},
close(){
this.$emit("close")
},
loadTasksToXmIterationState(row){
this.load.edit=true;
loadTasksToXmIterationState({id:row.id}).then(res=>{
this.load.edit=false;
var tips =res.data.tips;
if(tips.isOk){
this.getXmIterations();
}
this.$notify({showClose: true, message: tips.msg, type: tips.isOk?'success':'error'});
});
},
},//end methods
components: {
//
},
mounted() {
this.$nextTick(() => {
this.maxTableHeight = util.calcTableMaxHeight(this.$refs.table.$el);
this.getXmIterations();
});
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.more-label-font{
text-align:center;
float:left;
padding-top:5px;
}
.font-class{
color: rgba(116, 85, 85, 0.493);
}
.align-right{
float: right;
}
</style>

4
src/views/xm/core/xmIterationLink/XmIterationLinkForProduct.vue

@ -45,8 +45,8 @@
import { listXmIterationLinkWithProductInfo,addXmIterationLink, delXmIterationLink, batchDelXmIterationLink } from '@/api/xm/core/xmIterationLink';
import { mapGetters } from 'vuex'
import XmProductSelect from '../xmProduct/XmProductSelect.vue';
import XmIterationSelect from '../xmIteration/XmIterationSelect.vue';
import XmProductSelect from '@/views/xm/core/components/XmProductSelect.vue'
import XmIterationSelect from '@/views/xm/core/components/XmIterationSelect.vue';
import XmIterationAdd from '../xmIteration/XmIterationAdd';//

5
src/views/xm/core/xmIterationLink/XmIterationLinkForProject.vue

@ -45,8 +45,9 @@
import { listXmIterationLinkWithProjectInfo,addXmIterationLink, delXmIterationLink, batchDelXmIterationLink } from '@/api/xm/core/xmIterationLink';
import { mapGetters } from 'vuex'
import XmProjectSelect from '../xmProject/XmProjectSelect.vue';
import XmIterationSelect from '../xmIteration/XmIterationSelect.vue';
import XmProjectSelect from '@/views/xm/core/components/XmProjectSelect.vue'
;
import XmIterationSelect from '@/views/xm/core/components/XmIterationSelect.vue';
import XmIterationAdd from '../xmIteration/XmIterationAdd';//

93
src/views/xm/core/xmIterationMenu/XmIterationMenuMng.vue

@ -1,25 +1,21 @@
<template>
<section class="page-container padding">
<section class="page-container">
<el-row >
<el-col :span="8" v-if="!xmIteration">
<xm-iteration-mng :simple="true" @row-click="onIterationRowClick" @clear-select="onIterationClearSelect"></xm-iteration-mng>
</el-col>
<el-col :span="xmIteration?24:16">
<el-col :span="10">
<el-row class="padding-left">
<el-input v-model="filters.key" style="width: 20%;" placeholder="模糊查询">
<el-input v-model="filters.key" style="width: 60%;" placeholder="模糊查询">
</el-input>
<el-button type="primary" v-loading="load.list" :disabled="load.list==true" v-on:click="searchXmIterationMenus" icon="el-icon-search"></el-button>
<span style="float:right;">
<el-button type="primary" @click="showAdd" icon="el-icon-plus" round>加入更多需求到迭代计划</el-button>
<el-button type="danger" @click="batchDel" icon="el-icon-right">批量移出</el-button>
<el-button type="danger" @click="batchDel" icon="el-icon-right">批量移出</el-button>
</span>
</el-row>
<el-row class="page-main padding-top padding-left">
<!--列表 XmIterationMenu 迭代定义-->
<el-table ref="table" :height="maxTableHeight" :data="xmIterationMenusTreeData" default-expand-all row-key="menuId" :tree-props="{children: 'children', hasChildren: 'hasChildren'}" @sort-change="sortChange" highlight-current-row v-loading="load.list" border @selection-change="selsChange" @row-click="rowClick" style="width: 100%;">
<el-table ref="table" :height="maxTableHeight" :data="xmIterationMenusTreeData" row-key="menuId" :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 type="selection" width="45"></el-table-column>
<el-table-column prop="menuName" label="需求名称" min-width="140" >
@ -39,14 +35,7 @@
</span>
</template>
</el-table-column>
<el-table-column prop="productId" label="产品" min-width="120" >
</el-table-column>
<el-table-column prop="iterationName" label="迭代" min-width="120" >
</el-table-column>
<el-table-column prop="mmUsername" label="责任人" width="140" >
</el-table-column>
<el-table-column label="操作" width="160" fixed="right">
<el-table-column label="操作" width="100" fixed="right">
<template slot-scope="scope">
<el-button type="primary" @click="handleDel(scope.row,scope.$index)" icon="el-icon-right">移出</el-button>
</template>
@ -55,19 +44,20 @@
<el-pagination layout="total, sizes, prev, pager, 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>
</el-col>
<el-drawer append-to-body title="需求选择" :visible.sync="menuVisible" size="70%" :close-on-click-modal="false">
<xm-menu-select :xm-iteration="xmIteration" :visible="menuVisible" :is-select-menu="true" :multi="true" @menus-selected="onSelectedMenus" ></xm-menu-select>
</el-drawer>
</el-row>
<el-col :span="14">
<xm-menu-select ref="menusSelect" iterationFilterType="not-join-curr-iteration" checkScope="0" :xm-product="{id:xmIteration.productId}" :xm-iteration="xmIteration" :visible="menuVisible" :is-select-menu="true" :multi="true" @menus-selected="onSelectedMenus" ></xm-menu-select>
</el-col>
</el-row>
</section>
</template>
<script>
import util from '@/common/js/util';//
import treeTool from '@/common/js/treeTool';//
import config from '@/common/config';//
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmIterationMenu, delXmIterationMenu, batchDelXmIterationMenu,batchAddXmIterationMenu } from '@/api/xm/core/xmIterationMenu';
import XmIterationMng from '../xmIteration/XmIterationSelect';//
import XmIterationMng from '@/views/xm/core/components/XmIterationSelect';//
import { mapGetters } from 'vuex'
import xmMenuSelect from '../xmMenu/XmMenuSelect';
@ -78,10 +68,11 @@
...mapGetters([
'userInfo','roles'
]),
xmIterationMenusTreeData(){
var data= this.translateDataToTree(this.xmIterationMenus);
return data;
xmIterationMenusTreeData() {
let xmMenus = JSON.parse(JSON.stringify(this.xmIterationMenus || []));
let xmMenusTreeData = treeTool.translateDataToTree(xmMenus,"pmenuId","menuId");
return xmMenusTreeData;
},
},
watch:{
@ -200,10 +191,6 @@
},
// XmIterationMenu
showAdd: function () {
if(!this.roles.some(i=>i.roleid=='iterationAdmin')){
this.$notify({showClose: true, message: "只有迭代管理员可以操作", type: 'error' });
return ;
}
this.menuVisible = true;
//this.addForm=Object.assign({}, this.editForm);
},
@ -231,6 +218,8 @@
var tips=res.data.tips;
if(tips.isOk){
this.pageInfo.count=true;
this.$refs.menusSelect.reloadChildren([row]);
this.getXmIterationMenus();
}
this.$notify({showClose: true, message: tips.msg, type: tips.isOk?'success':'error' });
@ -254,6 +243,7 @@
this.load.del=false;
var tips=res.data.tips;
if( tips.isOk ){
this.$refs.menusSelect.reloadChildren(this.sels);
this.pageInfo.count=true;
this.getXmIterationMenus();
}
@ -264,50 +254,6 @@
rowClick: function(row, event, column){
this.$emit('row-click',row, event, column);// @row-click="rowClick"
},
/**begin 自定义函数请在下面加**/
/**begin 自定义函数请在下面加**/
translateDataToTree(data2) {
var data=JSON.parse(JSON.stringify(data2));
let parents = data.filter(value =>{
//
if(value.pmenuId == 'undefined' || value.pmenuId == null || value.pmenuId == ''){
return true;
//
}else if(data.some(i=>value.pmenuId==i.menuId)){
return false;
}else {
return true
}
})
let children = data.filter(value =>{
if(data.some(i=>value.pmenuId==i.menuId)){
return true;
}else{
return false;
}
})
let translator = (parents, children) => {
parents.forEach((parent) => {
children.forEach((current, index) => {
if (current.pmenuId === parent.menuId) {
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
},
onSelectedMenus(menus){
if(!menus || menus.length==0){
this.menuVisible=false
@ -323,6 +269,7 @@
var tips = res.data.tips
if(tips.isOk){
this.getXmIterationMenus()
this.$refs.menusSelect.reloadChildren(menus);
}
this.$notify({showClose: true, message: tips.msg, type: tips.isOk?'success':'error'});
})

6
src/views/xm/core/xmMenu/XmMenuAdd.vue

@ -117,9 +117,9 @@
<el-input-number :disabled="addForm.calcType!=='2' && addForm.ntype==='1'" style="width:200px;" v-model="addForm.mactWorkload" :precision="2" :step="8" :min="0" placeholder="实际工时(小时)"></el-input-number> &nbsp;h
</el-form-item>
<font color="blue" style="font-size:10px;">控制规则:
<br>下级往上汇总需求池的数据来自直接下级的需求池(需求)的数据之和逐级往上汇总
<br>由任务汇总 需求(不包括需求池)的数据来自与该需求关联的任务的数据之和
<br>手工填报 需求(不包括需求池)数据来自手工填报无论是否关联了任务都不从任务汇总
<br>下级往上汇总工时数据按 &nbsp;用户故事->特性->史诗 &nbsp;这样的汇总关系将数据逐级往上汇总
<br>由任务汇总 用户故事的工时数据由任务汇总
<br>手工填报 用户故事的工时数据来自手工填报无论是否关联了任务都不从任务汇总
</font>
</el-collapse-item>
<el-collapse-item title="成本" name="3">

40
src/views/xm/core/xmMenu/XmMenuEdit.vue

@ -111,21 +111,21 @@
</el-form-item>
<el-form-item label="当前进度" prop="mactRate" >
<el-progress style="width:80%;" :stroke-width="26" :percentage="editForm.mactRate?addForm.mactRate:0"></el-progress>
<el-progress style="width:40%;" :stroke-width="26" :percentage="editForm.mactRate?editForm.mactRate:0"></el-progress>
</el-form-item>
<el-form-item label="预估工期" prop="budgetHours">
<el-input-number :disabled="editForm.calcType!=='2' && editForm.ntype==='1'" style="width:200px;" v-model="editForm.budgetHours" :precision="2" :step="8" :min="0" placeholder="预计工期(小时)"></el-input-number>&nbsp;h
<el-input-number :disabled="editForm.calcType!=='2'" style="width:200px;" v-model="editForm.budgetHours" :precision="2" :step="8" :min="0" placeholder="预计工期(小时)"></el-input-number>&nbsp;h
</el-form-item>
<el-form-item label="预估工时" prop="budgetWorkload">
<el-input-number :disabled="editForm.calcType!=='2' && editForm.ntype==='1'" style="width:200px;" v-model="editForm.budgetWorkload" :precision="2" :step="8" :min="0" placeholder="预计工时(人时)"></el-input-number> &nbsp;h
<el-input-number :disabled="editForm.calcType!=='2'" style="width:200px;" v-model="editForm.budgetWorkload" :precision="2" :step="8" :min="0" placeholder="预计工时(人时)"></el-input-number> &nbsp;h
</el-form-item>
<el-form-item label="实际工时" prop="mactWorkload">
<el-input-number :disabled="editForm.calcType!=='2' && editForm.ntype==='1'" style="width:200px;" v-model="editForm.mactWorkload" :precision="2" :step="8" :min="0" placeholder="实际工时(人时)"></el-input-number> &nbsp;h
<el-input-number :disabled="editForm.calcType!=='2'" style="width:200px;" v-model="editForm.mactWorkload" :precision="2" :step="8" :min="0" placeholder="实际工时(人时)"></el-input-number> &nbsp;h
</el-form-item>
<font color="blue" style="font-size:10px;">控制规则:
<br>下级往上汇总需求池的数据来自直接下级的需求池(需求)的数据之和逐级往上汇总
<br>由任务汇总 需求(不包括需求池)的数据来自与该需求关联的任务的数据之和
<br>手工填报 需求(不包括需求池)数据来自手工填报无论是否关联了任务都不从任务汇总
<br>下级往上汇总工时数据按 &nbsp;用户故事->特性->史诗 &nbsp;这样的汇总关系将数据逐级往上汇总
<br>由任务汇总 用户故事的工时数据由任务汇总
<br>手工填报 用户故事的工时数据来自手工填报无论是否关联了任务都不从任务汇总
</font>
</el-collapse-item>
<el-collapse-item title="成本" name="3">
@ -235,7 +235,31 @@ import XmMenuExchangeMng from '../xmMenuExchange/XmMenuExchangeMng.vue';
if(visible==true){
//
}
}
},
'editForm.mactWorkload':function(val,oldVal){
if(!this.editForm.budgetWorkload){
return;
}
if(val==0||!val){
return;
}
this.editForm.mactRate=Math.round(val/this.editForm.budgetWorkload*100)
if( this.editForm.mactRate>100){
this.editForm.mactRate=100;
}
},
'editForm.budgetWorkload':function(val,oldVal){
if(!this.editForm.mactWorkload){
return;
}
if(val==0||!val){
return;
}
this.editForm.mactRate=Math.round(this.editForm.mactWorkload/val*100)
if( this.editForm.mactRate>100){
this.editForm.mactRate=100;
}
}
},
data() {
return {

217
src/views/xm/core/xmMenu/XmMenuMng.vue

@ -3,51 +3,31 @@
<el-row v-show=" !batchEditVisible">
<el-col :span="24" class="padding-left">
<el-row>
<xm-product-select ref="xmProductSelect1" style="display:inline;" v-if="!xmProduct && !xmIteration" :auto-select="false" :link-project-id="selProject?selProject.id:null" @row-click="onProductSelected" :iterationId="xmIteration?xmIteration.id:null" @clear-select="onProductClearSelect"></xm-product-select>
<el-popover v-if=" !filters.iteration || !filters.iteration.id"
placement="bottom"
width="400"
trigger="manual"
v-model="productVisible">
<xm-product-select v-if="!xmProduct" :auto-select="false" :sel-project="selProject" @row-click="onProductSelected" ref="xmProductMng" :xm-iteration="xmIteration" :simple="true" @clear-select="onProductClearSelect" @close="productVisible=false"></xm-product-select>
<el-link title="产品,点击选择、清除选择" @click="productVisible=true" type="warning" slot="reference" v-if="!xmProduct" icon="el-icon-search"><font style="font-size:14px;">{{filters.product?filters.product.productName:'选择产品'}}</font></el-link>
</el-popover>
<xm-it-select style="width: 120px;" clearable :product-id="filters.product?filters.product.id:null" :link-project-id="selProject?selProject.id:null" placeholder="迭代" @change="onIterationSelected" @clear="onIterationClearSelect">
<xm-it-select v-if="!xmIteration || !xmIteration.id" style="display:inline;" :auto-select="false" :product-id="filters.product?filters.product.id:null" :link-project-id="selProject?selProject.id:null" placeholder="迭代" @row-click="onIterationSelected" @clear="onIterationClearSelect">
</xm-it-select>
<el-select v-model="filters.taskFilterType" placeholder="已分配任务的需求?" clearable style="width: 160px;">
<el-select v-model="filters.taskFilterType" placeholder="已分配任务的需求?" clearable v-if="selProject &&selProject.id">
<el-option value="not-join-any-project" label="未分配过任务的需求"></el-option>
<el-option value="join-any-project" label="已分配过任务的需求"></el-option>
<el-option value="not-join-curr-project" :label="'未分配任务到项目【'+selProject.name+'】'" v-if="selProject && selProject.id"></el-option>
<el-option value="join-curr-project" :label="'已分配任务到项目【'+selProject.name+'】'" v-if="selProject && selProject.id"></el-option>
</el-select>
<el-select v-model="filters.iterationFilterType" placeholder="加入过迭代?" clearable style="width: 160px;">
<el-select v-if=" !selProject || !selProject.id" v-model="filters.iterationFilterType" placeholder="加入过迭代?" clearable>
<el-option value="not-join-any-iteration" label="未加入过迭代"></el-option>
<el-option value="join-any-iteration" label="已加入过迭代"></el-option>
<el-option value="not-join-curr-iteration" :label="'未加入迭代【'+filters.iteration.iterationName+'】'" v-if="filters.iteration && filters.iteration.id"></el-option>
<el-option value="join-curr-iteration" :label="'已加入本迭代【'+filters.iteration.iterationName+'】'" v-if="filters.iteration && filters.iteration.id"></el-option>
</el-select>
<el-select class="hidden-lg-and-down" v-model="filters.dtype" clearable placeholder="需求类型" style="width: 120px;">
<el-option v-for="i in this.dicts.demandType" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
<el-select class="hidden-lg-and-down" v-model="filters.source" placeholder="需求来源" clearable style="width: 120px;">
<el-option v-for="i in this.dicts.demandSource" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
<el-select class="hidden-lg-and-down" v-model="filters.dlvl" placeholder="需求层次" clearable style="width: 120px;">
<el-option v-for="i in this.dicts.demandLvl" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
<el-button class="hidden-lg-and-down" v-if="!filters.tags||filters.tags.length==0" @click.native="tagSelectVisible=true">标签条件</el-button>
<el-tag class="hidden-lg-and-down" v-else @click="tagSelectVisible=true" closable @close="clearFiltersTag(filters.tags[0])">{{filters.tags[0].tagName.substr(0,5)}}({{filters.tags.length}})</el-tag>
<el-select class="hidden-lg-and-down" v-model="filters.priority" placeholder="优先级" clearable style="width: 100px;">
<el-select v-model="filters.priority" placeholder="优先级" clearable style="width: 100px;">
<el-option v-for="i in dicts.priority" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
<el-select class="hidden-md-and-down" v-model="filters.status" placeholder="需求状态" clearable style="width: 100px;">
<el-option :value="item.id" :label="item.name" v-for="(item,index) in dicts.menuStatus" :key="index"></el-option>
</el-select>
<el-input v-model="filters.key" style="width: 15%;" placeholder="需求名称查询" clearable>
<el-input v-model="filters.key" style="width: 220px;" placeholder="需求名称查询" clearable>
</el-input>
<el-button type="primary" v-loading="load.list" :disabled="load.list==true" v-on:click="searchXmMenus" icon="el-icon-search"></el-button>
@ -86,7 +66,30 @@
<el-button v-else @click="selectFiltersMmUser()">选责任人</el-button>
<el-button @click="setFiltersMmUserAsMySelf()">我的</el-button>
</el-col>
<el-col :span="24" style="padding-top:5px;" class="hidden-lg-and-up">
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">
需求是否已加入迭代:
</font>
<el-select v-model="filters.iterationFilterType" placeholder="加入过迭代?" clearable >
<el-option value="not-join-any-iteration" label="未加入过迭代"></el-option>
<el-option value="join-any-iteration" label="已加入过迭代"></el-option>
<el-option value="not-join-curr-iteration" :label="'未加入迭代【'+filters.iteration.iterationName+'】'" v-if="filters.iteration && filters.iteration.id"></el-option>
<el-option value="join-curr-iteration" :label="'已加入本迭代【'+filters.iteration.iterationName+'】'" v-if="filters.iteration && filters.iteration.id"></el-option>
</el-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" >
<font class="more-label-font">
需求是否已分配了任务:
</font>
<el-select v-model="filters.taskFilterType" placeholder="已分配任务的需求?" clearable >
<el-option value="not-join-any-project" label="未分配过任务的需求"></el-option>
<el-option value="join-any-project" label="已分配过任务的需求"></el-option>
<el-option value="not-join-curr-project" :label="'未分配任务到项目【'+selProject.name+'】'" v-if="selProject && selProject.id"></el-option>
<el-option value="join-curr-project" :label="'已分配任务到项目【'+selProject.name+'】'" v-if="selProject && selProject.id"></el-option>
</el-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" >
<font class="more-label-font">
需求类型:
</font>
@ -94,7 +97,7 @@
<el-option v-for="i in this.dicts.demandType" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" class="hidden-xl-only">
<el-col :span="24" style="padding-top:5px;" >
<font class="more-label-font">
需求来源:
</font>
@ -102,7 +105,7 @@
<el-option v-for="i in this.dicts.demandSource" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" class="hidden-xl-only">
<el-col :span="24" style="padding-top:5px;" >
<font class="more-label-font">
需求层次:
</font>
@ -110,7 +113,7 @@
<el-option v-for="i in this.dicts.demandLvl" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" class="hidden-xl-only">
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">
优先级:
</font>
@ -118,7 +121,7 @@
<el-option v-for="i in dicts.priority" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" class="hidden-lg-and-up">
<el-col :span="24" style="padding-top:5px;" >
<font class="more-label-font">
需求状态:
</font>
@ -126,20 +129,13 @@
<el-option :value="item.id" :label="item.name" v-for="(item,index) in dicts.menuStatus" :key="index"></el-option>
</el-select>
</el-col>
<el-button class="hidden-lg-and-down" v-if="!filters.tags||filters.tags.length==0" @click.native="tagSelectVisible=true">标签条件</el-button>
<el-tag class="hidden-lg-and-down" v-else @click="tagSelectVisible=true" closable @close="clearFiltersTag(filters.tags[0])">{{filters.tags[0].tagName.substr(0,5)}}({{filters.tags.length}})</el-tag>
<el-col :span="24" style="padding-top:5px;">
<el-button type="primary" @click="searchXmMenus" icon="el-icon-search">查询</el-button>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<el-button v-if=" batchEditVisible==false " @click="handleExport" icon="el-icon-download">导出</el-button>
<el-button v-if=" batchEditVisible==false&&disabledMng!=false " @click="loadTasksToXmMenuState" icon="el-icon-s-marketing">汇总进度</el-button>
</el-col>
</el-row>
<el-button slot="reference" icon="el-icon-more"></el-button>
@ -178,15 +174,16 @@
<el-button type="primary" round slot="reference" icon="el-icon-plus"></el-button>
</el-popover>
<!--<el-button @click="batchEditVisible=true" icon="el-icon-edit" title="批量修改"></el-button> -->
<el-button @click="showParentMenu" icon="el-icon-top" title="更换上级"></el-button>
<el-button v-if="disabledMng!=false" type="danger" @click="batchDel" icon="el-icon-delete" title="删除"></el-button>
<el-button class="hidden-md-and-down" v-if=" batchEditVisible==false&&disabledMng!=false " @click="loadTasksToXmMenuState" icon="el-icon-s-marketing" title="汇总进度"></el-button>
<xm-table-config ref="tableConfig" style="display:inline;" :table="$refs.table"></xm-table-config>
</span>
</el-row>
<el-row class="padding-top">
<el-table :row-style="{height:'60px'}" lazy :load="loadXmMenusLazy" stripe fit border ref="table" :height="maxTableHeight" :data="xmMenusTreeData" current-row-key="menuId" row-key="menuId" :tree-props="{children: 'children', hasChildren: 'childrenCnt'}" @sort-change="sortChange" highlight-current-row v-loading="load.list" @selection-change="selsChange" @row-click="rowClick">
<el-table :cell-style="cellStyleCalc" :header-cell-style="cellStyleCalc" :row-style="{height:'60px'}" lazy :load="loadXmMenusLazy" stripe fit border ref="table" :height="maxTableHeight" :data="xmMenusTreeData" current-row-key="menuId" row-key="menuId" :tree-props="{children: 'children', hasChildren: 'childrenCnt'}" @sort-change="sortChange" highlight-current-row v-loading="load.list" @selection-change="selsChange" @row-click="rowClick">
<el-table-column sortable type="selection" width="40"></el-table-column>
<el-table-column prop="menuName" label="需求名称" min-width="300" fixed="left">
@ -226,6 +223,7 @@
</el-table-column>
<template>
<el-table-column prop="productId" label="产品" width="100" show-overflow-tooltip sortable>
</el-table-column>
<el-table-column prop="status" label="状态" min-width="80" sortable>
@ -240,7 +238,7 @@
</span>
</template>
</el-table-column>
<el-table-column prop="dtype" label="类型" width="100" sortable>
<el-table-column prop="dtype" label="类型" width="100" sortable v-if="false">
<template slot-scope="scope">
<div class="cell-text">
{{formaterByDicts(scope.row,'dtype',scope.row.dtype)}}
@ -252,7 +250,7 @@
</span>
</template>
</el-table-column>
<el-table-column prop="source" label="来源" width="100" :formatter="formaterByDicts" show-overflow-tooltip sortable>
<el-table-column prop="source" label="来源" width="100" :formatter="formaterByDicts" show-overflow-tooltip sortable v-if="false">
<template slot-scope="scope">
<div class="cell-text">
{{formaterByDicts(scope.row,'source',scope.row.source)}}
@ -289,31 +287,9 @@
</span>
</template>
</el-table-column>
<el-table-column prop="iterationName" label="迭代" min-width="120" show-overflow-tooltip sortable>
<template slot="header">
迭代
<el-popover
placement="top"
width="300"
v-model="linkIterationPopoverVisible">
<p>将需求加入还是移出迭代 <span v-if="filters.iteration && filters.iteration.id">{{filters.iteration.iterationName}}</span>?</p>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="doBatchDelXmIterationMenu">移出</el-button>
<el-button type="primary" size="mini" @click="doBatchAddXmIterationMenu">加入</el-button>
</div>
<el-button type="text" slot="reference" icon="el-icon-edit" title="点击设置需求与迭代的关联关系" @click="linkIterationPopoverVisible=true">关联</el-button>
</el-popover>
</template>
<el-table-column prop="iterationName" label="迭代" width="150" show-overflow-tooltip sortable>
<template slot-scope="scope">
<div class="cell-text">
{{scope.row.iterationName}}
</div>
<span class="cell-bar">
<xm-it-select :product-id="filters.product?filters.product.id:null" :link-project-id="selProject?selProject.id:null" v-model="scope.row.iterationId" placeholder="迭代" style="display:block;" @change="editXmMenuSomeFields(scope.row,'iterationId',$event)">
</xm-it-select>
</span>
</template>
</el-table-column>
@ -327,8 +303,18 @@
</el-table-column>
<el-table-column prop="finishRate" label="进度" min-width="80" show-overflow-tooltip sortable>
<template slot-scope="scope">
<span v-if="scope.row.finishRate"><el-tag :type="scope.row.finishRate>=100?'success':'warning'">{{scope.row.finishRate}}%</el-tag></span>
<div class="cell-text" v-if="scope.row.calcType!=='2'">
<span v-if="scope.row.finishRate"><el-tag :type="scope.row.finishRate>=100?'success':'warning'">{{scope.row.finishRate}}%</el-tag></span>
</div>
<div class="cell-text" v-else>
<span v-if="scope.row.mactRate"><el-tag :type="scope.row.mactRate>=100?'success':'warning'">{{scope.row.mactRate}}%</el-tag></span>
</div>
<span class="cell-bar">
<xm-menu-workload :menu="scope.row" placeholder="工时" style="display:block;" @submit="editXmMenuSomeFields(scope.row,'workload',$event)">
</xm-menu-workload>
</span>
</template>
</el-table-column>
<el-table-column prop="bugs" label="缺陷" min-width="100" show-overflow-tooltip sortable>
@ -360,7 +346,7 @@
<span>{{scope.row.mmUsername}} </span>
</template>
</el-table-column>
</template>
</el-table>
@ -400,10 +386,6 @@
</el-drawer>
</el-col>
</el-row>
<el-row v-if="batchEditVisible">
<xm-menu-mng-batch :xm-menus="xmMenus" :dicts="dicts" @no-batch-edit="noBatchEdit" :product="filters.product"></xm-menu-mng-batch>
</el-row>
<el-pagination layout="total, sizes, prev, pager, 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-drawer append-to-body title="标签条件" :visible.sync="tagSelectVisible" size="60%">
@ -448,14 +430,15 @@
import XmMenuAdd from './XmMenuAdd';//
import XmMenuEdit from './XmMenuEdit';//
import XmMenuMngBatch from './XmMenuMngBatch';//
import XmProductSelect from '../xmProduct/XmProductSelect';//
import XmProductSelect from '@/views/xm/core/components/XmProductSelect';//
import XmMenuTemplateMng from '../xmMenuTemplate/XmMenuTemplateMng';//
import XmMenuRichDetail from './XmMenuRichDetail';
import XmTaskList from '../xmTask/XmTaskList';
import XmTaskMng from '../xmTask/XmTaskMng';
import XmTaskListForMenu from '../xmTask/XmTaskListForMenu';
import XmIterationSelect from '../xmIteration/XmIterationSelect';//
import XmItSelect from '@/views/xm/core/components/XmItSelect';//
import XmItSelect from '@/views/xm/core/components/XmIterationSelect.vue';//
import XmMenuWorkload from '@/views/xm/core/components/XmMenuWorkload';//
import XmTableConfig from '@/views/xm/core/components/XmTableConfig';//
import UsersSelect from "@/views/mdp/sys/user/UsersSelect";
import XmMenuSelect from "../xmMenu/XmMenuSelect";
@ -472,7 +455,7 @@
'userInfo','roles'
]),
xmMenusTreeData() {
xmMenusTreeData() {
let xmMenus = JSON.parse(JSON.stringify(this.xmMenus || []));
let xmMenusTreeData = treeTool.translateDataToTree(xmMenus,"pmenuId","menuId");
return xmMenusTreeData;
@ -498,6 +481,7 @@
const endDate = new Date();
beginDate.setTime(beginDate.getTime() - 3600 * 1000 * 24 * 7 * 4 * 12 );
return {
columnsConfig:[/**{label:'',property:'',isShow:true} */],
filters: {
key: '',
product:null,
@ -515,7 +499,7 @@
xmMenus: [],//
pageInfo:{//
total:0,//0>0
pageSize:50,//
pageSize:20,//
count:false,//
pageNum:1,//1
orderFields:[],// ['sex','student_id']
@ -633,7 +617,13 @@
}
if(this.filters.taskFilterType){
params.taskFilterType=this.filters.taskFilterType
params.projectId=this.selProject.id
if(params.taskFilterType==='not-join-curr-project'){
params.projectId=this.selProject.id
}
if(params.taskFilterType==='join-curr-project'){
params.projectId=this.selProject.id
}
params.ntype="0"
}
if(this.selProject && this.selProject.id){
@ -735,8 +725,8 @@
// XmMenu xm_project_menu
showEdit: function ( row,index ) {
this.editFormVisible = true;
this.editForm = Object.assign({}, row);
this.editFormVisible = true;
},
// XmMenu xm_project_menu
showAdd: function (dclass) {
@ -747,7 +737,7 @@
this.addForm.dclass=dclass
this.addFormVisible = true;
}else{
this.productVisible=true;
this.$refs.xmProductSelect1.productVisible=true;
this.$notify({showClose: true, message: "请先选择一个产品", type: 'warning'});
}
@ -797,13 +787,11 @@
},
onIterationSelected:function(iteration){
this.filters.iteration=iteration
this.iterationVisible=false;
this.xmMenus=[]
this.getXmMenus()
},
onIterationClearSelect:function(){
this.filters.iteration=null
this.iterationVisible=false;
this.xmMenus=[]
this.getXmMenus()
},
@ -831,7 +819,7 @@
//xmMenu
batchDel: function () {
if(this.sels.length==0){
this.$notify({showClose: true, message: "请先选择要删除的需求或者需求池", type: 'warning'});
this.$notify({showClose: true, message: "请先选择要删除的需求", type: 'warning'});
return;
}
this.$confirm('确认删除选中的'+this.sels.length+'条数据吗?删除后数据不可恢复', '提示', {
@ -892,10 +880,6 @@
return dataList;
},
/**begin 自定义函数请在下面加**/
selectedMenu:function(row){
this.$emit("selected",row)
},
showImportFromMenuTemplate(row){
if(!this.filters.product){
this.$notify.error("请选择产品模板")
@ -972,14 +956,8 @@
}
}).catch( err => this.load.add=false );
},
toBatchEdit(){
this.batchEditVisible=true;
},
noBatchEdit(){
this.batchEditVisible=false;
this.getXmMenus();
},
showTaskList(row){
this.editForm=row
@ -1007,22 +985,6 @@
this.$notify({showClose: true, message: tips.msg, type: tips.isOk?'success':'error'});
});
},
showMenuExchange:function(row){
this.editForm=row
this. menuDetailVisible=true;
},
toProjectList:function(product){
this.$router.push({name:'xmProjectMng',params:{productId:product.id,productName:product.productName}})
},
toIterationList:function(row){
this.editForm=row
this.iterationVisible=true;
},
showTasks(row){
this.editForm=row
this.taskMngVisible=true
},
showTaskListForMenu(row){
this.editForm=row
@ -1227,8 +1189,10 @@
}else{
return;
}
}else {
params[fieldName]=$event;
}else if(fieldName==='workload'){
params={...params,...$event}
}else{
params[fieldName]=$event
}
editXmMenuSomeFields(params).then(res=>{
@ -1245,6 +1209,9 @@
i['tagIds']=params['tagIds']
this.fieldTagVisible=false;
}
if(fieldName==='workload'){
Object.assign(i,params)
}
})
}else{
if(fieldName==='tagIds'){
@ -1252,12 +1219,31 @@
row['tagIds']=params['tagIds']
this.fieldTagVisible=false;
}
if(fieldName==='iterationId'){
row['iterationName']=params['iterationName']
row['iterationId']=params['iterationId']
}
if(fieldName==='workload'){
Object.assign(row,params)
}
}
}else{
this.$notify({showClose:true,message:tips.msg,type:tips.isOk?'success':'error'})
}
})
},
cellStyleCalc({row, column, rowIndex, columnIndex}){
if(this.$refs.tableConfig && this.$refs.tableConfig.columnsConfig.length>0){
if(this.$refs.tableConfig.columnsConfig.some(i=>i.property==column.property&&i.isShow==false)){
return "display:none;"
}else{
return "";
}
}else{
return "";
}
}
},//end methods
components: {
'xm-menu-add':XmMenuAdd,
@ -1268,12 +1254,13 @@
XmTaskList,
XmTaskMng,
XmTaskListForMenu,
XmIterationSelect,
UsersSelect,
XmMenuMngBatch,
TagMng,
XmMenuSelect,
XmItSelect,
XmMenuWorkload,
XmTableConfig,
//
},
mounted() {

163
src/views/xm/core/xmMenu/XmMenuSelect.vue

@ -3,50 +3,23 @@
<el-row>
<el-col :span="24" style="padding-left:12px;" >
<el-row>
<el-popover
placement="bottom"
width="400"
trigger="manual"
v-model="productVisible">
<xm-product-select v-if="!xmProduct" :auto-select="false" :sel-project="selProject" @row-click="onProductSelected" ref="xmProductMng" :xm-iteration="xmIteration" :simple="true" @clear-select="onProductClearSelect" @close="productVisible=false"></xm-product-select>
<el-link title="产品,点击选择、清除选择" @click="productVisible=true" type="warning" slot="reference" v-if="!xmProduct" icon="el-icon-search"><font style="font-size:14px;">{{filters.product?filters.product.productName:'选择产品'}}</font></el-link>
</el-popover>
<el-popover
placement="bottom"
width="400"
trigger="manual"
v-model="iterationVisible">
<xm-iteration-select v-if="!xmIteration" :auto-select="false" :sel-project="selProject" @row-click="onIterationSelected" ref="xmProductMng" :xm-product="xmProduct" :simple="true" @clear-select="onIterationClearSelect" @close="iterationVisible=false"></xm-iteration-select>
<el-link title="迭代,点击选择、清除选择" @click="iterationVisible=true" type="warning" slot="reference" v-if="!xmIteration" icon="el-icon-search"><font style="font-size:14px;">{{filters.iteration?filters.iteration.iterationName:'选择迭代'}}</font></el-link>
</el-popover>
<el-select v-model="filters.taskFilterType" placeholder="已分配任务的需求?" clearable style="width: 160px;">
<el-option value="not-join-any-project" label="未分配过任务的需求"></el-option>
<el-option value="join-any-project" label="已分配过任务的需求"></el-option>
<el-option value="not-join-curr-project" :label="'未分配任务到项目【'+selProject.name+'】'" v-if="selProject && selProject.id"></el-option>
<el-option value="join-curr-project" :label="'已分配任务到项目【'+selProject.name+'】'" v-if="selProject && selProject.id"></el-option>
</el-select>
<el-select v-model="filters.iterationFilterType" placeholder="加入过迭代?" clearable style="width: 160px;">
<el-option value="not-join-any-iteration" label="未加入过迭代"></el-option>
<el-option value="join-any-iteration" label="已加入过迭代"></el-option>
<el-option value="not-join-curr-iteration" :label="'未加入迭代【'+filters.iteration.iterationName+'】'" v-if="filters.iteration && filters.iteration.id"></el-option>
<el-option value="join-curr-iteration" :label="'已加入本迭代【'+filters.iteration.iterationName+'】'" v-if="filters.iteration && filters.iteration.id"></el-option>
</el-select>
<el-select v-model="filters.dtype" clearable placeholder="需求类型">
<el-option v-for="i in this.dicts.demandType" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
<el-select v-model="filters.source" placeholder="需求来源" clearable>
<el-option v-for="i in this.dicts.demandSource" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
<el-select v-model="filters.dlvl" placeholder="需求层次" clearable class="hidden-md-and-down">
<el-option v-for="i in this.dicts.demandLvl" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</el-row>
<el-row>
<el-button class="hidden-md-and-down" v-if="!filters.tags||filters.tags.length==0" @click.native="tagSelectVisible=true">标签条件</el-button>
<el-tag class="hidden-md-and-down" v-else @click="tagSelectVisible=true" closable @close="clearFiltersTag(filters.tags[0])">{{filters.tags[0].tagName.substr(0,5)}}({{filters.tags.length}})</el-tag>
<el-select v-model="filters.priority" placeholder="优先级" clearable>
<xm-product-select style="display:inline;" v-if="!xmProduct&&!xmIteration" :auto-select="false" :link-project-id="selProject?selProject.id:null" @row-click="onProductSelected" ref="xmProductMng" :iteration-id="xmIteration?xmIteration.id:null" @clear-select="onProductClearSelect"></xm-product-select>
<xm-iteration-select style="display:inline;" v-if="!xmIteration" :auto-select="false" :link-project-id="selProject?selProject.id:null" @row-click="onIterationSelected" ref="xmIterationMng" :product-id="xmProduct?xmProduct.id:null" @clear-select="onIterationClearSelect"></xm-iteration-select>
<el-select v-model="filters.taskFilterType" placeholder="已分配任务的需求?" clearable v-if="taskFilterType">
<el-option value="not-join-any-project" label="未分配过任务的需求"></el-option>
<el-option value="join-any-project" label="已分配过任务的需求"></el-option>
<el-option value="not-join-curr-project" :label="'未分配任务到项目【'+selProject.name+'】'" v-if="selProject && selProject.id"></el-option>
<el-option value="join-curr-project" :label="'已分配任务到项目【'+selProject.name+'】'" v-if="selProject && selProject.id"></el-option>
</el-select>
<el-select v-model="filters.iterationFilterType" placeholder="加入过迭代?" clearable v-if="iterationFilterType">
<el-option value="not-join-any-iteration" label="未加入过迭代"></el-option>
<el-option value="join-any-iteration" label="已加入过迭代"></el-option>
<el-option value="not-join-curr-iteration" :label="'未加入迭代【'+filters.iteration.iterationName+'】'" v-if="filters.iteration && filters.iteration.id"></el-option>
<el-option value="join-curr-iteration" :label="'已加入本迭代【'+filters.iteration.iterationName+'】'" v-if="filters.iteration && filters.iteration.id"></el-option>
</el-select>
<el-select v-model="filters.priority" placeholder="优先级" clearable style="width: 100px;">
<el-option v-for="i in dicts.priority" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
<el-select v-model="filters.status" placeholder="需求状态" clearable style="width: 100px;">
@ -91,6 +64,62 @@
<el-button v-else @click="selectFiltersMmUser()">选责任人</el-button>
<el-button @click="setFiltersMmUserAsMySelf()">我的</el-button>
</el-col>
<el-col :span="24" style="padding-top:5px;" class="hidden-log-and-up">
<font class="more-label-font">
需求是否加入了迭代:
</font>
<el-select v-model="filters.iterationFilterType" placeholder="加入过迭代?" clearable >
<el-option value="not-join-any-iteration" label="未加入过迭代"></el-option>
<el-option value="join-any-iteration" label="已加入过迭代"></el-option>
<el-option value="not-join-curr-iteration" :label="'未加入迭代【'+filters.iteration.iterationName+'】'" v-if="filters.iteration && filters.iteration.id"></el-option>
<el-option value="join-curr-iteration" :label="'已加入本迭代【'+filters.iteration.iterationName+'】'" v-if="filters.iteration && filters.iteration.id"></el-option>
</el-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" class="hidden-log-and-up">
<font class="more-label-font">
需求是否分配了任务:
</font>
<el-select v-model="filters.taskFilterType" placeholder="已分配任务的需求?" clearable >
<el-option value="not-join-any-project" label="未分配过任务的需求"></el-option>
<el-option value="join-any-project" label="已分配过任务的需求"></el-option>
<el-option value="not-join-curr-project" :label="'未分配任务到项目【'+selProject.name+'】'" v-if="selProject && selProject.id"></el-option>
<el-option value="join-curr-project" :label="'已分配任务到项目【'+selProject.name+'】'" v-if="selProject && selProject.id"></el-option>
</el-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" class="hidden-log-and-up">
<font class="more-label-font">
需求层次:
</font>
<el-select v-model="filters.dlvl" placeholder="需求层次" clearable>
<el-option v-for="i in this.dicts.demandLvl" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" class="hidden-log-and-up">
<font class="more-label-font">
需求类型:
</font>
<el-select v-model="filters.dtype" clearable placeholder="需求类型" style="width: 100px;">
<el-option v-for="i in this.dicts.demandType" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" class="hidden-log-and-up">
<font class="more-label-font">
需求来源:
</font>
<el-select v-model="filters.source" placeholder="需求来源" clearable style="width: 100px;">
<el-option v-for="i in this.dicts.demandSource" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" class="hidden-log-and-up">
<font class="more-label-font">
需求层次:
</font>
<el-select v-model="filters.dlvl" placeholder="需求层次" clearable class="hidden-md-and-down" style="width: 100px;">
<el-option v-for="i in this.dicts.demandLvl" :label="i.name" :key="i.id" :value="i.id"></el-option>
</el-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" class="hidden-log-and-up">
<font class="more-label-font">
需求层次:
@ -106,7 +135,7 @@
<el-button slot="reference" icon="el-icon-more"></el-button>
</el-popover>
<el-button type="primary" v-if="multi" v-on:click="multiSelectedConfirm">确认选择</el-button>
<el-button style="float:right;" type="primary" v-if="multi" v-on:click="multiSelectedConfirm">确认选择</el-button>
</el-row>
<el-row style="padding-top:12px;">
<el-table ref="table" class="menu-table" lazy :load="loadMenusLazy" :height="maxTableHeight" :data="xmMenusTreeData" row-key="menuId" :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%;">
@ -124,15 +153,12 @@
<div v-if="scope.row.dclass=='3'" class="icon" style="background-color: rgb(79, 140, 255);">
<i class="el-icon-document"></i>
</div>
<span class="vlink" :class="scope.row.ntype==='1'?'el-icon-folder-opened':''" @click="toMenu(scope.row)">{{scope.row.seqNo}}&nbsp;
<span class="vlink" @click="toMenu(scope.row)">{{scope.row.seqNo}}&nbsp;
{{scope.row.menuName}}</span>
</template>
</el-table-column>
<el-table-column prop="productId" label="产品" min-width="100" > </el-table-column>
<el-table-column prop="iterationName" label="迭代" min-width="140" > </el-table-column>
<el-table-column prop="mmUsername" label="责任人" width="140" >
</el-table-column>
<el-table-column label="操作" width="100" fixed="right" >
<template slot-scope="scope">
<el-button :disabled="checkScope && checkScope!==scope.row.ntype" type="primary" @click="selectedMenu( scope.row,scope.$index)">选择</el-button>
@ -165,19 +191,19 @@
//import Sticky from '@/components/Sticky' // header
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmMenu } from '@/api/xm/core/xmMenu';
import XmProductSelect from '../xmProduct/XmProductSelect';//
import XmProductSelect from '@/views/xm/core/components/XmProductSelect';//
import XmMenuRichDetail from './XmMenuRichDetail';
import UsersSelect from "@/views/mdp/sys/user/UsersSelect";
import TagMng from "@/views/mdp/arc/tag/TagMng";
import XmIterationSelect from '../xmIteration/XmIterationSelect';//
import XmIterationSelect from '@/views/xm/core/components/XmIterationSelect';//
import {sn} from '@/common/js/sequence'
import { mapGetters } from 'vuex'
export default {
props:['isSelectMenu','multi','visible','xmIteration','xmProduct','selProject','checkScope'/**0-需求,1-需求池 */],
props:['isSelectMenu','multi','visible','xmIteration','xmProduct','selProject','checkScope'/**0-需求,1-需求池 */,'iterationFilterType','taskFilterType'],
computed: {
...mapGetters([
'userInfo','roles'
@ -211,6 +237,7 @@
const endDate = new Date();
beginDate.setTime(beginDate.getTime() - 3600 * 1000 * 24 * 7 * 4 * 6 );
return {
maps:new Map(),
filters: {
key: '',
product:null,
@ -312,7 +339,13 @@
}
if(this.filters.taskFilterType){
params.taskFilterType=this.filters.taskFilterType
params.projectId=this.selProject.id
if(params.taskFilterType==='not-join-curr-project'){
params.projectId=this.selProject.id
}
if(params.taskFilterType==='join-curr-project'){
params.projectId=this.selProject.id
}
params.ntype="0"
}
if(this.selProject && this.selProject.id){
@ -349,9 +382,9 @@
}
return params;
},
loadMenusLazy(row, treeNode, resolve) {
var params={pmenuId:row.menuId}
loadMenusLazy(tree, treeNode, resolve) {
this.maps.set(tree.menuId, { tree, treeNode, resolve }) //
var params={pmenuId:tree.menuId}
params=this.getParams(params);
params.isTop=""
this.load.list = true;
@ -366,6 +399,9 @@
}
}).catch( err => this.load.list = false );
},
reloadChildren(rows){
treeTool.reloadAllChildren(this.$refs.table,this.maps,rows,'pmenuId',this.loadMenusLazy)
},
// XmMenu xm_project_menu
getXmMenus() {
@ -385,13 +421,14 @@
if( this.filters.product && this.filters.product.id){
params.productId=this.filters.product.id
}else {
this.$notify({showClose: true, message: "请先选择产品", type: 'warning' });
return;
//params.xxx=xxxxx
}
params=this.getParams(params)
if(!params.productId && !params.iterationId && !params.linkIterationId){
this.$notify({showClose: true, message: "请先选择产品", type: 'warning' });
return;
}
params.withParents="1"
this.load.list = true;
listXmMenu(params).then((res) => {
@ -514,7 +551,13 @@
this.filters.iterationFilterType='join-curr-iteration'
this.filters.iteration=this.xmIteration
}
if(this.iterationFilterType){
this.filters.iterationFilterType=this.iterationFilterType
}
if(this.taskFilterType){
this.filters.taskFilterType=this.taskFilterType
}
this.filters.product=this.xmProduct
this.getXmMenus();
});

19
src/views/xm/core/xmProduct/XmProductForLinkComplex.vue

@ -5,13 +5,7 @@
<el-tabs type="border-card" :value="showPanel" @tab-click="tabClick">
<el-tab-pane disabled>
<div slot="label">
<el-popover
placement="bottom"
width="400"
trigger="click">
<xm-product-select ref="xmProductSelect" :auto-select="true" :sel-project="selProject" :xm-iteration="xmIteration" @row-click="onProductRowClick" @clear-select="onProductClearSelect"></xm-product-select>
<el-link type="warning" slot="reference" icon="el-icon-search"><font style="font-size:14px;">{{xmProduct?xmProduct.productName:'选择产品'}}</font></el-link>
</el-popover>
<xm-product-select ref="xmProductSelect" :auto-select="true" :link-project-id="selProject?selProject.id:null" :iterationId="xmIteration?xmIteration.id:null" @row-click="onProductRowClick" @clear-select="onProductClearSelect"></xm-product-select>
</div>
</el-tab-pane>
<el-tab-pane disabled>
@ -36,13 +30,12 @@
<xm-product-edit v-if="showPanel=='detail'" :xm-product="xmProduct"></xm-product-edit>
</el-tab-pane>
<el-tab-pane label="配置关联的项目" lazy name="productProjectLink" v-if="xmProduct && xmProduct.id && !selProject">
<xm-product-project-link-mng v-if="showPanel=='productProjectLink'" :xm-product="xmProduct"></xm-product-project-link-mng>
</el-tab-pane>
<el-tab-pane label="迭代" name="iterationProductLink" v-if="xmProduct && xmProduct.id" >
<xm-iteration-mng v-if="showPanel=='iterationProductLink'" :xm-product="xmProduct"></xm-iteration-mng>
</el-tab-pane>
<el-tab-pane label="配置关联的项目" lazy name="productProjectLink" v-if="xmProduct && xmProduct.id">
<xm-product-project-link-mng v-if="showPanel=='productProjectLink'" :xm-product="xmProduct"></xm-product-project-link-mng>
</el-tab-pane>
<el-tab-pane label="需求" lazy name="menus" v-if="xmProduct && xmProduct.id">
<xm-menu-mng v-if="xmProduct && showPanel=='menus'" :xm-product="xmProduct" :xm-iteration="xmIteration" :sel-project="selProject" :disabled-mng="true"></xm-menu-mng>
</el-tab-pane>
@ -74,10 +67,9 @@
import XmProductMng from './XmProductMng.vue';
import XmTaskMng from '../xmTask/XmTaskMng.vue';
import XmQuestionMng from '../xmQuestion/XmQuestionMng.vue';
import XmProjectList from '../xmProject/XmProjectList.vue';
import XmProjectForLink from '../xmProject/XmProjectForLink.vue';
import XmProductSelect from './XmProductSelect.vue';
import XmProductSelect from '@/views/xm/core/components/XmProductSelect.vue';
import XmProductProjectForLink from './XmProductProjectForLink.vue';
import XmProductOverview from "./XmProductOverview";
import XmIterationLinkForProduct from '../xmIterationLink/XmIterationLinkForProduct.vue';
@ -140,7 +132,6 @@ import XmProductEdit from './XmProductEdit.vue';
XmTaskMng,
XmQuestionMng,
XmProductSelect,
XmProjectList,
XmProjectForLink,
XmProductProjectForLink,
XmProductOverview,

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

@ -185,9 +185,6 @@
import util from '@/common/js/util';//
//import Sticky from '@/components/Sticky' // header
//import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmProject,editStatus , delXmProject, batchDelXmProject } from '@/api/xm/core/xmProject';
import XmProjectAdd from '../xmProject/XmProjectAdd';//
import XmProjectEdit from '../xmProject/XmProjectEdit';//
import XmProjectForLinkComplex from '../xmProject/XmProjectForLinkComplex';//
import { mapGetters } from 'vuex';

12
src/views/xm/core/xmProduct/XmProductMng.vue

@ -254,10 +254,6 @@
<el-drawer title="选择项目" :visible.sync="projectVisible" size="60%" append-to-body>
<xm-project-list @select="onProjectSelected"></xm-project-list>
</el-drawer>
<el-drawer title="选择产品" :visible.sync="productSelectVisible" size="60%" append-to-body>
<xm-product-select @row-click="onXmProductSelect"></xm-product-select>
</el-drawer>
<el-drawer title="迭代报告" :visible.sync="iterationSelectVisible" fullscreen append-to-body :close-on-click-modal="false">
<xm-iteration-select @row-click="onXmIterationSelect"></xm-iteration-select>
</el-drawer>
@ -309,13 +305,12 @@
import XmProductEdit from './XmProductEdit';//
import XmProductTplMng from './XmProductTplMng';//
import { mapGetters } from 'vuex'
import XmIterationMng from '../xmIteration/XmIterationSelect';//
import XmIterationMng from '@/views/xm/core/components/XmIterationSelect';//
import XmProductStateMng from '../xmProductState/XmProductStateMng';//
import UsersSelect from "@/views/mdp/sys/user/UsersSelect";
import XmProjectList from '../xmProject/XmProjectList.vue';
import XmIterationSelect from '../xmIteration/XmIterationSelect.vue';
import XmProductSelect from './XmProductSelect.vue';
import XmIterationSelect from '@/views/xm/core/components/XmIterationSelect.vue';
import XmProductSelect from '@/views/xm/core/components/XmProductSelect.vue';
import Guider from '@/components/Guider/Index.js';
@ -723,7 +718,6 @@
XmIterationMng,
XmProductStateMng,
UsersSelect,
XmProjectList,
XmIterationSelect,
XmProductSelect,
XmProductTplMng,

347
src/views/xm/core/xmProduct/XmProductSelect.vue

@ -1,347 +0,0 @@
<template>
<section>
<el-row >
<!--列表 XmProduct 产品表-->
<el-table ref="table" :height="maxTableHeight" :data="xmProducts" :row-class-name="tableRowClassName" @sort-change="sortChange" :highlight-current-row="true" current-row-key="id" v-loading="load.list" border @selection-change="selsChange" @row-click="rowClick" style="width: 100%;">
<el-table-column label="序号" type="index" width="50" > </el-table-column>
<el-table-column v-if="isSelectProduct==true" label="产品编码" prop="id" min-width="100" show-overflow-tooltip > </el-table-column>
<el-table-column prop="productName" label="产品名称" show-overflow-tooltip>
<template slot="header" slot-scope="scope">
产品名称 <el-button type="text" @click="clearSelect">清空所选</el-button>&nbsp;<el-button type="text" @click="close">关闭</el-button>
<el-popover
placement="top-start"
title=""
width="400"
trigger="hover" >
<el-row>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">
产品查询范围
</font>
<el-select v-model="filters.queryScope" style="width:100%;" placeholder="产品查询范围">
<el-option :label="userInfo.branchName+'机构下所有的产品'" value="branchId"></el-option>
<el-option label="我相关的产品" value="compete"></el-option>
<el-option label="按产品编号精确查找" value="productId"></el-option>
<el-option label="后台智能匹配" value=""></el-option>
</el-select>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<el-input v-if="filters.queryScope=='productId'" v-model="filters.id" style="width:100%;" placeholder="输入产品编号" @keyup.enter.native="searchXmProducts">
</el-input>
</el-col>
<el-col v-show="!selProject&&filters.queryScope!='productId'" :span="24" style="padding-top:5px;">
<font class="more-label-font">创建时间:</font>
<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-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">
产品名称:
</font>
<el-input v-model="filters.key" style="width:100%;" placeholder="输入产品名字关键字">
</el-input>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">
产品经理:
</font>
<el-tag v-if="filters.pmUser" closable @click="selectFiltersPmUser" @close="clearFiltersPmUser()">{{filters.pmUser.username}}</el-tag>
<el-button v-else @click="selectFiltersPmUser()">选责任人</el-button>
<el-button @click="setFiltersPmUserAsMySelf()">我的</el-button>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<el-button type="primary" @click="searchXmProducts" >查询</el-button>
</el-col>
</el-row>
<el-button type="text" slot="reference" style="float:right;">更多条件</el-button>
</el-popover>
</template>
<template slot-scope="scope">
<font>{{scope.row.productName}}</font>
</template>
</el-table-column>
<el-table-column v-if="isSelectProduct==true" label="操作" width="100" fixed="right" >
<template slot-scope="scope">
<el-button type="primary" @click="selectedProduct( scope.row,scope.$index)">选择</el-button>
</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>
<el-drawer title="选择员工" :visible.sync="selectFiltersPmUserVisible" size="60%" append-to-body>
<users-select @confirm="onFiltersPmUserSelected" ref="usersSelect"></users-select>
</el-drawer>
</section>
</template>
<script>
import util from '@/common/js/util';//
//import Sticky from '@/components/Sticky' // header
//import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmProductWithState } from '@/api/xm/core/xmProduct';
import { mapGetters } from 'vuex'
import UsersSelect from "@/views/mdp/sys/user/UsersSelect";
import { loadTasksToXmProductState } from '@/api/xm/core/xmProductState';
export default {
props:['isSelectProduct','selProject','xmIteration','autoSelect'],
computed: {
...mapGetters([
'userInfo','roles'
])
},
watch:{
xmIteration(){
this.getXmProducts();
},
selProject(){
this.getXmProducts();
}
},
data() {
const beginDate = new Date();
const endDate = new Date();
beginDate.setTime(beginDate.getTime() - 3600 * 1000 * 24 * 7 * 4 * 12 );
return {
filters: {
key: '',
queryScope:'compete',
id:'',//
pmUser:null,//
},
xmProducts: [],//
pageInfo:{//
total:0,//0>0
pageSize:10,//
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:{},// params=[{categoryId:'0001',itemCode:'sex'}] {'sex':[{optionValue:'1',optionName:'',seqOrder:'1',fp:'',isDefault:'0'},{optionValue:'2',optionName:'',seqOrder:'2',fp:'',isDefault:'0'}]}
addFormVisible: false,//xmProduct
//xmProduct
addForm: {
id:'',productName:'',branchId:'',remark:''
},
editFormVisible: false,//
//xmProduct
editForm: {
id:'',productName:'',branchId:'',remark:''
},
iterationVisible:false,
productStateVisible:false,
selectFiltersPmUserVisible:false,
maxTableHeight:300,
dateRanger: [ ],
pickerOptions: util.pickerOptions('datarange'),
/**begin 自定义属性请在下面加 请加备注**/
/**end 自定义属性请在上面加 请加备注**/
}
},//end data
methods: {
handleSizeChange(pageSize) {
this.pageInfo.pageSize=pageSize;
this.getXmProducts();
},
handleCurrentChange(pageNum) {
this.pageInfo.pageNum = pageNum;
this.getXmProducts();
},
// 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.getXmProducts();
},
searchXmProducts(){
this.pageInfo.count=true;
this.getXmProducts();
},
// XmProduct
getXmProducts() {
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(",")
}
if(this.filters.key!==""){
params.key="%"+this.filters.key+"%"
}else{
//params.xxx=xxxxx
}
if(this.selProject){
params.projectId=this.selProject.id
}
if(this.xmIteration){
params.iterationId=this.xmIteration.id
}
params.queryScope=this.filters.queryScope
if(this.filters.queryScope=='productId'){
if(!this.filters.id){
this.$notify({showClose: true, message:"您选择了按产品编号精确查找模式,请输入产品编号", type: 'error' });
return;
}
params.id=this.filters.id
}
if(this.filters.queryScope=="branchId"){
params.branchId=this.userInfo.branchId
params.projectId=null;
}
if(!this.selProject && !this.xmIteration && this.filters.queryScope!='productId'){
if(this.dateRanger&&this.dateRanger.length==2){
params.ctimeStart=this.dateRanger[0]
params.ctimeEnd=this.dateRanger[1]
}
}
this.load.list = true;
listXmProductWithState(params).then((res) => {
var tips=res.data.tips;
if(tips.isOk){
this.pageInfo.total = res.data.total;
this.pageInfo.count=false;
this.xmProducts = res.data.data;
if(this.autoSelect===true&&this.xmProducts.length>0){
var row=this.xmProducts[0];
this.$refs.table.setCurrentRow(row);
this.rowClick(row);
}
}else{
this.$notify({showClose: true, message: tips.msg, type: 'error' });
}
this.load.list = false;
}).catch( err => this.load.list = false );
},
//xmProduct
selsChange: function (sels) {
this.sels = sels;
},
rowClick: function(row, event, column){
this.editForm=row
this.$emit('row-click',row, event, column);// @row-click="rowClick"
},
selectedProduct:function(row){
this.editForm=row
this.$emit('selected',row);
},
/**begin 自定义函数请在下面加**/
clearFiltersPmUser:function(){
this.filters.pmUser=null;
this.searchXmProducts();
},
selectFiltersPmUser(){
this.selectFiltersPmUserVisible=true;
},
onFiltersPmUserSelected(users){
if(users && users.length>0){
this.filters.pmUser=users[0]
}else{
this.filters.pmUser=null;
}
this.selectFiltersPmUserVisible=false;
this.searchXmProducts();
},
setFiltersPmUserAsMySelf(){
this.filters.pmUser=this.userInfo;
this.searchXmProducts();
},
loadTasksToXmProductState: function (row) {
this.load.edit=true;
let params = { productId: row.id };
loadTasksToXmProductState(params).then((res) => {
this.load.edit=false;
var tips=res.data.tips;
if(tips.isOk){
this.pageInfo.count=true;
this.getXmProducts();
}
this.$notify({showClose: true, message: tips.msg, type: tips.isOk?'success':'error' });
}).catch( err => this.load.edit=false );
},
tableRowClassName({row, rowIndex}) {
if (row.id == this.editForm.id) {
return 'success-row';
}
return '';
},
clearSelect(){
this.$refs.table.setCurrentRow();
this.$emit("clear-select");
},
close(){
this.$emit("close");
}
},//end methods
components: {
UsersSelect,
//
},
mounted() {
this.$nextTick(() => {
this.maxTableHeight = util.calcTableMaxHeight(this.$refs.table.$el);
this.getXmProducts();
});
}
}
</script>
<style scoped>
.more-label-font{
text-align:center;
float:left;
padding-top:5px;
}
.align-right{
float: right;
}
</style>

29
src/views/xm/core/xmProductProjectLink/XmProductProjectLinkMng.vue

@ -2,9 +2,15 @@
<section class="app-container">
<el-row>
<span style="float:right;">
<el-button type="primary" v-if="selProject" @click="productVisible=true" icon="el-icon-plus" round> 选择更多产品加入项目 </el-button>
<el-button type="primary" v-if="xmProduct" @click="projectVisible=true" icon="el-icon-plus" round> 选择更多项目加入产品 </el-button>
</span>
<xm-product-select @row-click="onProductSelect" :autoSelect="false" v-if="selProject && selProject.id">
<font slot="title">选择更多产品加入项目</font>
</xm-product-select>
<xm-project-select :autoSelect="false" @row-click="onProjectSelect" v-if="xmProduct && xmProduct.id">
<font slot="title">
选择更多项目加入产品
</font>
</xm-project-select>
</span>
</el-row>
<el-row style="padding-top:10px;">
<!--列表 XmProductProjectLink 产品与项目的关联关系表一般由产品经理挂接项目到产品上-->
@ -22,15 +28,6 @@
<el-pagination layout="total, sizes, prev, pager, 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>
<el-drawer title="选择产品" :visible.sync="productVisible" size="50%" append-to-body :close-on-click-modal="false">
<xm-product-select @row-click="onProductSelect"></xm-product-select>
</el-drawer>
<el-drawer title="选择项目" :visible.sync="projectVisible" size="50%" append-to-body :close-on-click-modal="false">
<xm-project-select @row-click="onProjectSelect"></xm-project-select>
</el-drawer>
</section>
</template>
@ -42,8 +39,8 @@
import XmProductProjectLinkAdd from './XmProductProjectLinkAdd';//
import XmProductProjectLinkEdit from './XmProductProjectLinkEdit';//
import { mapGetters } from 'vuex'
import XmProductSelect from '../xmProduct/XmProductSelect.vue';
import XmProjectSelect from '../xmProject/XmProjectSelect.vue';
import XmProductSelect from '@/views/xm/core/components/XmProductSelect.vue'
import XmProjectSelect from '@/views/xm/core/components/XmProjectSelect.vue'
export default {
props:['selProject','xmProduct'],
@ -92,9 +89,7 @@ import XmProjectSelect from '../xmProject/XmProjectSelect.vue';
projectId:'',productId:'',ctime:'',cuserid:'',cusername:'',linkStatus:''
},
maxTableHeight:300,
productVisible:false,
projectVisible:false,
}
}
},//end data
methods: {
handleSizeChange(pageSize) {

537
src/views/xm/core/xmProject/XmProjectAdd.vue

@ -1,537 +0,0 @@
<template>
<section class="page-container padding border">
<el-row class="page-main " :style="{overflowX:'auto',height:maxTableHeight+'px'}" ref="table">
<!--编辑界面 XmProject xm_project-->
<el-form :model="addForm" label-width="120px" :rules="addFormRules" ref="addForm">
<el-form-item label="项目代号" prop="code">
<el-input v-model="addForm.code" placeholder="项目代号,不可为空" >
<template slot="append">
<el-button type="text" @click="createProjectCode">自动生成</el-button>
</template>
</el-input>
<font color="blue" style="font-size:10px;">项目代号为合同上的项目代号甲乙方共享;项目内部编号为 &nbsp;代号-四位随机码</font>
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="addForm.name" placeholder="项目名称" ></el-input>
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item label="项目类型" prop="xmType">
<el-select v-model="addForm.xmType">
<el-option v-for="(i,index) in dicts['projectType']" :label="i.name" :value="i.id" :key="index"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="优先级" prop="priority">
<el-select v-model="addForm.priority">
<el-option v-for="(i,index) in dicts['priority']" :label="i.name" :value="i.id" :key="index"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="预算控制">
<el-form-item prop="budgetCtrl">
<el-checkbox v-model="addForm.budgetCtrl" true-label="1" false-label="0" >总预算控制</el-checkbox>
<font style="font-size:12px;" color="blue">项目计划总预算不能大于项目总预算</font>
</el-form-item>
<el-form-item label="" prop="phaseBudgetCtrl">
<el-checkbox v-model="addForm.phaseBudgetCtrl" true-label="1" false-label="0" >项目计划预算控制</el-checkbox>
<font style="font-size:12px;" color="blue">下级计划总预算不能大于上级计划总预算每条计划的预算金额必须大于其关联任务的预算合计</font>
</el-form-item>
<el-form-item label="" prop="phaseActCtrl">
<el-checkbox v-model="addForm.phaseActCtrl" true-label="1" false-label="0" >实际金额控制</el-checkbox>
<font style="font-size:12px;" color="blue">每条计划实际金额不能大于预算金额;每条计划的预算金额必须大于其关联的任务的实际金额合计</font>
</el-form-item>
</el-form-item>
<el-row>
<el-col :span="8">
<el-form-item label="总控" prop="admUserid">
<el-input readonly v-model="addForm.admUsername" @click.native="showUserVisible('admUserid')"></el-input>
<font style="font-size:12px;" color="blue"></font>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="项目经理" prop="pmUserid">
<el-input readonly v-model="addForm.pmUsername" @click.native="showUserVisible('pmUserid')"></el-input>
<font style="font-size:12px;" color="blue"></font>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="副经理、助理" prop="assUserid">
<el-input readonly v-model="addForm.assUsername" @click.native="showUserVisible('assUserid')"></el-input>
<font style="font-size:12px;" color="blue"></font>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="项目预估" >
<el-tabs>
<el-tab-pane label="工作量及人力成本" name="planWorkload">
<el-row>
<el-date-picker
v-model="dateRanger"
class="hidden-sm-and-down"
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:150px;" type="number" v-model="addForm.planWorkingHours" :precision="2" :step="8" :min="0" placeholder="预计工时"></el-input><el-tag>参考工时{{autoParams.planWorkingHours}}小时,工作日{{autoParams.weekday}}</el-tag>
</el-row>
<el-divider></el-divider>
<el-row>
<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-divider></el-divider>
<el-row>
<el-col :span="4">内购</el-col>
<el-col :span="4"><el-input style="width:120px;" type="number" v-model="addForm.planIuserCnt" :precision="0" :step="1" :min="0" placeholder="内购人数"></el-input>
</el-col>
<el-col :span="4">{{autoParams.planIuserWorkload}}人时</el-col>
<el-col :span="4"><el-input style="width:120px;" type="number" v-model="addForm.planIuserPrice" :precision="0" :step="1" :min="0" placeholder="预计内部人时单价"></el-input> </el-col>
<el-col :span="8">{{this.toFixed(autoParams.planIuserAt)}},{{this.toFixed(autoParams.planIuserAt/10000)}} 万元</el-col>
</el-row>
<el-divider></el-divider>
<el-row>
<el-col :span="4">外购</el-col>
<el-col :span="4"><el-input style="width:120px;" type="number" v-model="addForm.planOuserCnt" :precision="0" :step="1" :min="0" placeholder="外购人数"></el-input>
</el-col>
<el-col :span="4">{{autoParams.planOuserWorkload}}人时</el-col>
<el-col :span="4"><el-input style="width:120px;" type="number" v-model="addForm.planOuserPrice" :precision="0" :step="1" :min="0" placeholder="预计外购人时单价"></el-input> </el-col>
<el-col :span="4">{{autoParams.planOuserAt }} {{autoParams.planOuserAt/10000 }}万元</el-col>
</el-row>
<el-divider></el-divider>
<el-row>
<el-col :span="4">合计</el-col>
<el-col :span="4"> {{autoParams.planOuserCnt+autoParams.planIuserCnt}}
</el-col>
<el-col :span="4">{{autoParams.planOuserWorkload+autoParams.planIuserWorkload }}人时,{{ (autoParams.planOuserWorkload+autoParams.planIuserWorkload)/8/20 }}人月 </el-col>
<el-col :span="4">平均{{ (parseFloat2(autoParams.planOuserPrice) + parseFloat2(autoParams.planIuserPrice))/2}}/人时</el-col>
<el-col :span="8">{{autoParams.planTotalCost}} {{(autoParams.planTotalCost)/10000}} 万元</el-col>
</el-row>
</el-tab-pane>
<el-tab-pane label="成本总览" name="planTotalCost">
<el-row>
内购 <el-input style="width:120px;" type="number" v-model="addForm.planIuserAt" :precision="2" :step="1000" :min="0" placeholder="内部人力成本总预算"></el-input> <el-tag> {{this.toFixed(autoParams.planIuserAt/10000)}}万元</el-tag>
外购 <el-input style="width:120px;" type="number" v-model="addForm.planOuserAt" :precision="2" :step="1000" :min="0" placeholder="外购人力成本总预算"></el-input> <el-tag> {{this.toFixed(autoParams.planOuserAt/10000)}}万元</el-tag>
非人力<el-input style="width:120px;" type="number" v-model="addForm.planNouserAt" :precision="2" :step="1000" :min="0" placeholder="人力成本总预算"></el-input> <el-tag> {{this.toFixed( autoParams.planNouserAt/10000)}}万元</el-tag>
</el-row>
<el-divider></el-divider>
<el-row>
合计 <el-input style="width:150px;" type="number" v-model="addForm.planTotalCost" :precision="2" :step="1000" :min="0" placeholder="总成本预算"></el-input> <el-tag> {{this.toFixed(autoParams.planTotalCost/10000)}}万元</el-tag>
</el-row>
</el-tab-pane>
<el-tab-pane label="合同收入" name="contractAmt">
<el-row>
预计收款总额<el-input style="width:150px;" type="number" v-model="addForm.totalReceivables" :precision="2" :step="1000" :min="0" placeholder="预计总收款金额"></el-input> <el-tag> {{this.toFixed(autoParams.totalReceivables/10000)}}</el-tag>
合同总金额 <el-input style="width:150px;" type="number" v-model="addForm.contractAmt" :precision="2" :step="1000" :min="0" placeholder="合同总金额"></el-input> <el-tag> {{this.toFixed(autoParams.contractAmt/10000)}}</el-tag>
</el-row>
</el-tab-pane>
<el-tab-pane label="毛利水平" name="budgetTaxRate">
<el-row>
税率<el-input style="width:120px;" type="number" v-model="addForm.taxRate" :precision="2" :step="0.01" :min="0" :max="0.99" placeholder="税率"></el-input>
考核标准毛利率<el-input style="width:120px;" type="number" v-model="addForm.budgetMarginRate" :precision="2" :step="0.01" :min="0" :max="0.99" placeholder="毛利率"></el-input>
当前毛利率为<el-tag>{{toFixed(parseFloat2(autoParams.currentBudgetMarginRate)*100,2)}}%</el-tag>
</el-row>
</el-tab-pane>
</el-tabs>
</el-form-item>
<el-form-item label="项目描述" prop="description">
<el-input type="textarea" :rows="6" v-model="addForm.description" placeholder="项目描述" ></el-input>
</el-form-item>
</el-form>
</el-row>
<el-row>
<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>
<el-drawer append-to-body title="选择员工" :visible.sync="userSelectVisible" size="60%">
<users-select isSingleUser=true @confirm="onUserSelected" ref="usersSelect"></users-select>
</el-drawer>
</section>
</template>
<script>
import util from '@/common/js/util';//
import {sn} from '@/common/js/sequence';//
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { addXmProject,createProjectCode } from '@/api/xm/core/xmProject';
import { mapGetters } from 'vuex';
import UsersSelect from "@/views/mdp/sys/user/UsersSelect";
export default {
computed: {
...mapGetters([
'userInfo','roles'
]),
autoParams:function(){
var planOuserPrice=this.toFixed(this.addForm.planOuserPrice)
var planIuserPrice=this.toFixed(this.addForm.planIuserPrice)
var planOuserCnt=this.toFixed(this.addForm.planOuserCnt)
var planIuserCnt=this.toFixed(this.addForm.planIuserCnt)
var planWorkingHours=this.toFixed(this.addForm.planWorkingHours )
var planNouserAt=this.toFixed(this.addForm.planNouserAt )
var budgetMarginRate=this.toFixed(this.addForm.budgetMarginRate,4 )
var taxRate=this.toFixed(this.addForm.taxRate,4)
if(planOuserPrice==null || planOuserPrice==''){
planOuserPrice=100
}
if(planIuserPrice==null || planIuserPrice==''){
planIuserPrice=80
}
if(planOuserCnt==null || planOuserCnt==''){
planOuserCnt=0.0
}
if(planIuserCnt==null || planIuserCnt==''){
planIuserCnt=0.0
}
if(planNouserAt==null || planNouserAt==''){
planNouserAt=0.0
}
if(budgetMarginRate==null || budgetMarginRate==''){
budgetMarginRate=0.4
}
if(planWorkingHours==null || planWorkingHours==''){
planWorkingHours=0.0
}
if(taxRate==null || taxRate==''){
taxRate=0.03
}
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]));
if(this.addForm.planWorkingHours==null || this.addForm.planWorkingHours=='' || this.addForm.planWorkingHours<=0){
planWorkingHours=weekday * 8
}
}
autoParams.weekday=weekday
autoParams.planWorkingHours=planWorkingHours
autoParams.planOuserPrice=planOuserPrice
autoParams.planIuserPrice=planIuserPrice
autoParams.planOuserCnt=planOuserCnt
autoParams.planIuserCnt=planIuserCnt
autoParams.taxRate=taxRate
autoParams.planIuserWorkload= planIuserCnt*planWorkingHours
autoParams.planOuserWorkload= planOuserCnt*planWorkingHours
autoParams.planWorkload= planIuserCnt*planWorkingHours + planOuserCnt*planWorkingHours
autoParams.planOuserAt= planOuserCnt * planWorkingHours * planOuserPrice
autoParams.planIuserAt= planIuserCnt * planWorkingHours * planIuserPrice
autoParams.planNouserAt= planNouserAt
autoParams.budgetMarginRate=budgetMarginRate
autoParams.planTotalCost= autoParams.planOuserAt + autoParams.planIuserAt + autoParams.planNouserAt
autoParams.totalReceivables=autoParams.planTotalCost/(1-budgetMarginRate)/ (1-taxRate)
autoParams.contractAmt =autoParams.totalReceivables
var totalReceivables=this.addForm.totalReceivables
if(totalReceivables==null || totalReceivables=='' || isNaN(totalReceivables)){
autoParams.currentBudgetMarginRate=-99
}else{
autoParams.currentBudgetMarginRate= this.toFixed(1-this.addForm.planTotalCost/(this.addForm.totalReceivables* (1-taxRate)),4)
}
// 1.=-/×100%=/×100%
// 2.=1/×100%
//totalReceivables=budgetMarginRate *
//budgetMarginRate=(totalReceivables* (1-taxRate)-planTotalCost)/totalReceivables* (1-taxRate)=1-planTotalCost/(totalReceivables* (1-taxRate))
//1-budgetMarginRate = planTotalCost/(totalReceivables* (1-taxRate))
// planTotalCost/(1-budgetMarginRate) =totalReceivables* (1-taxRate)
// totalReceivables=planTotalCost/(1-budgetMarginRate)/ (1-taxRate)
return autoParams
},
planTotalAt:function(){
return {
planOuserAt:this.addForm.planOuserAt,
planIuserAt:this.addForm.planIuserAt,
planNouserAt:this.addForm.planNouserAt,
}
},
totalReceivables:function(){
return this.addForm.totalReceivables
}
},
props:['visible','xmProduct'],
watch: {
'visible':function(visible) {
if(visible==true){
}
},
'planTotalAt':{
handler(planTotalAt){
this.addForm.planTotalCost=this.toFixed(this.parseFloat2(planTotalAt.planOuserAt)+this.parseFloat2(planTotalAt.planIuserAt)+this.parseFloat2(planTotalAt.planNouserAt))
//this.addForm.totalReceivables=this.toFixed(this.parseFloat2(this.addForm.planTotalCost) * (1+0.3))
},
deep:true
},
'totalReceivables':function(){
//this.addForm.budgetMarginRate=this.toFixed((this.addForm.totalReceivables-this.addForm.planTotalCost)/this.addForm.totalReceivables,4)
},
autoParams(){
this.fillPlanWorkingHoursToField()
this.fillPlanCostAtToField();
this.fillTotalReceivablesToField();
this.fillBudgetMarginRateToField()
},
},
data() {
const beginDate = new Date();
const endDate = new Date();
endDate.setTime(beginDate.getTime() + 3600 * 1000 * 24 * 7 * 4);
return {
filters: {
ids: [],
},
dicts:{
projectType:[],
priority:[],
priority:[],
projectStatus:[],
},// 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 },//...
addFormRules: {
name: [{
required: true, message: '项目名称不可为空' , trigger: 'change'
}],
code: [{
required: true, message: '项目代号不可为空', trigger: 'change'
}],
xmType: [{
required: true, message: '项目类型不可为空', trigger: 'change'
}],
priority: [{
required: true, message: '优先级不可为空', trigger: 'change'
}],
admUserid: [{
required: true, message: '项目总控不能为空', trigger: 'change'
}],
pmUserid: [{
required: true, message: '项目经理不能为空', trigger: 'change'
}],
},
// XmProject xm_project
addForm: {
id:'',code:'',name:'',xmType:'',startTime:'',endTime:'',urgent:'',priority:'',description:'',createUserid:'',createUsername:'',createTime:'',assess:'',assessRemarks:'',status:'',branchId:'',planTotalCost:0,bizProcInstId:'',bizFlowState:'',taxRate:0.06,planNouserAt:0,planIuserAt:0,planOuserAt:0,locked:'',baseTime:'',baseRemark:'',baselineId:'',planWorkload:0,totalReceivables:0,budgetMarginRate:0.13,contractAmt:0,planIuserPrice:85,planOuserPrice:100,planOuserCnt:1,planIuserCnt:1,planWorkingHours:0,planIuserWorkload:0,planOuserWorkload:0,budgetCtrl:'0',admUserid:'',admUsername:'',pmUserid:'',pmUsername:'',assUserid:'',assUsername:''
},
/**begin 在下面加自定义属性,记得补上面的一个逗号**/
xmGroups:[],
userSelectType: "",
userSelectVisible: false,
groupSelectVisible:false,
/**begin 在下面加自定义属性,记得补上面的一个逗号**/
dateRanger: [ ],
pickerOptions: util.pickerOptions('datarange'),
currUserType:'',
userSelectVisible:false,
maxTableHeight:300,
/**end 在上面加自定义属性**/
}//end return
},//end data
methods: {
//
//
showProjectGroups:function(){
this.groupSelectVisible=true;
},
//
onGroupSelected(groups){
this.xmGroups=groups;
this.groupSelectVisible=false;
},
// @cancel="addFormVisible=false"
handleCancel:function(){
this.$emit('cancel');
},
//XmProject xm_project@submit="afterEditSubmit"
addSubmit: function () {
if (
this.dateRanger != null &&
this.dateRanger.length == 2
) {
this.addForm.startTime = this.dateRanger[0]
this.addForm.endTime = this.dateRanger[1]
}else{
this.$notify({showClose: true, message: "请输入开始日期和结束日期", type: 'error' });
return;
}
this.$refs.addForm.validate((valid) => {
if (valid) {
var msg=this.xmProduct&&this.xmProduct.id?'将自动关联产品【'+this.xmProduct.productName+'】':'';
this.$confirm('确认提交吗?'+msg, '提示', {}).then(() => {
this.load.add=true
let params = Object.assign({}, this.addForm);
if(this.xmProduct && this.xmProduct.id){
params.links=[{productId:this.xmProduct.id}]
}
params.planIuserWorkload=this.autoParams.planIuserWorkload
params.planOuserWorkload=this.autoParams.planOuserWorkload
params.planWorkload=this.autoParams.planWorkload
addXmProject(params).then((res) => {
this.load.add=false;
var tips=res.data.tips;
if(tips.isOk){
this.$emit('submit',res.data.data);// @submit="afterEditSubmit"
}
this.$notify({showClose: true, message: tips.msg, type: tips.isOk?'success':'error' });
}).catch( err =>this.load.add=false);
});
}else{
this.$notify({showClose: true, message: "表单检查不通过,请修改后提交", type:'error'});
}
});
},
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);
},
fillPlanWorkingHoursToField:function(){
this.addForm.planWorkingHours=this.toFixed(this.autoParams.planWorkingHours)
},
fillPlanCostAtToField:function(){
this.addForm.planNouserAt=this.toFixed(this.autoParams.planNouserAt)
this.addForm.planOuserAt=this.toFixed(this.autoParams.planOuserAt )
this.addForm.planIuserAt=this.toFixed(this.autoParams.planIuserAt )
this.addForm.planTotalCost=this.toFixed(this.autoParams.planTotalCost)
},
fillTotalReceivablesToField:function(){
this.addForm.totalReceivables=this.toFixed(this.autoParams.totalReceivables )
this.addForm.contractAmt=this.toFixed(this.autoParams.contractAmt )
},
fillBudgetMarginRateToField:function(){
this.addForm.budgetMarginRate=this.toFixed(this.autoParams.budgetMarginRate,4)
},
createProjectCode(){
createProjectCode({}).then(res=>{
var tips=res.data.tips;
if(tips.isOk){
this.addForm.code=res.data.data
}
this.$notify({showClose: true, message: tips.msg, type: tips.isOk?'success':'error' });
})
},
showUserVisible(userType){
this.currUserType=userType
this.userSelectVisible=true;
},
//
onUserSelected: function(users) {
this.userSelectVisible = false;
var user={userid:'',username:''};
if(users && users.length>0){
user=users[0]
}
if(this.currUserType=='admUserid'){
this.addForm.admUserid=user.userid
this.addForm.admUsername=user.username
}else if(this.currUserType=='assUserid'){
this.addForm.assUserid=user.userid
this.addForm.assUsername=user.username
}else if(this.currUserType=='pmUserid'){
this.addForm.pmUserid=user.userid
this.addForm.pmUsername=user.username
}
this.currUserType="";
},
/**end 在上面加自定义方法**/
},//end method
components: {
UsersSelect,
},
mounted() {
this.maxTableHeight=util.calcTableMaxHeight(this.$refs.table.$el);
this.addForm.pmUserid=this.userInfo.userid
this.addForm.pmUsername=this.userInfo.username
this.addForm.admUserid=this.userInfo.userid
this.addForm.admUsername=this.userInfo.username
this.addForm.assUserid=this.userInfo.userid
this.addForm.assUsername=this.userInfo.username
initSimpleDicts('all',['projectType','priority','projectStatus']).then(res=>{
this.dicts=res.data.data;
})
}
}
</script>
<style scoped>
.line{
float:right;
width: 100%;
height: 1px;
margin-top: -0.5em;
background:#d4c4c4;
position: relative;
text-align: center;
}
</style>

296
src/views/xm/core/xmProject/XmProjectEdit.vue

@ -14,37 +14,67 @@
<el-collapse value="1" accordion>
<el-collapse-item title="基本信息" name="1">
<el-form-item label="项目代号|名称" prop="name">
<el-input v-model="editForm.code" placeholder="项目代号,不可为空" style="width:20%;" ></el-input><el-input style="width:80%;" v-model="editForm.name" placeholder="" ></el-input>
<font color="blue" style="font-size:10px;">项目代号为合同上的项目代号甲乙方共享;项目内部编号为 &nbsp;代号-四位随机码</font>
<el-row>
<span v-if="opType!=='add'" style="float:right;">
<el-button v-loading="load.edit" type="primary" @click.native="editSubmit" :disabled="load.edit==true">保存</el-button>
<el-button icon="el-icon-watch" type="warning" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_baseinfo_change_approva'})">基本信息修改申请</el-button>
</span>
</el-row>
<el-form-item label="项目代号" prop="code" v-if="opType==='add'">
<el-input v-model="editForm.code" placeholder="项目代号,不可为空" >
<template slot="append">
<el-button type="text" @click.native="createProjectCode">自动生成</el-button>
</template>
</el-input>
<font color="blue" style="font-size:10px;">项目代号为合同上的项目代号甲乙方共享;项目内部编号为 &nbsp;代号-四位随机码</font>
</el-form-item>
<el-form-item label="项目属性" prop="xmType">
<el-select v-model="editForm.xmType">
<el-option v-for="(i,index) in dicts['projectType']" :label="i.name" :value="i.id" :key="index"></el-option>
</el-select>
<el-select v-model="editForm.priority">
<el-option v-for="(i,index) in dicts['priority']" :label="i.name" :value="i.id" :key="index"></el-option>
</el-select>
<el-form-item label="名称" prop="name" v-if="opType==='add'">
<el-input v-model="editForm.name" placeholder="项目名称" ></el-input>
</el-form-item>
<el-form-item label="预算控制">
<el-form-item prop="budgetCtrl">
<el-checkbox v-model="editForm.budgetCtrl" true-label="1" false-label="0" >总预算控制</el-checkbox>
<font style="font-size:12px;" color="blue">项目计划总预算不能大于项目总预算</font>
</el-form-item>
<el-form-item label="" prop="phaseBudgetCtrl">
<el-checkbox v-model="editForm.phaseBudgetCtrl" true-label="1" false-label="0" >项目计划预算控制</el-checkbox>
<font style="font-size:12px;" color="blue">下级计划总预算不能大于上级计划总预算每条计划的预算金额必须大于其关联任务的预算合计</font>
</el-form-item>
<el-form-item label="" prop="phaseActCtrl">
<el-checkbox v-model="editForm.phaseActCtrl" true-label="1" false-label="0" >实际金额控制</el-checkbox>
<font style="font-size:12px;" color="blue">每条计划实际金额不能大于预算金额;每条计划的预算金额必须大于其关联的任务的实际金额合计</font>
</el-form-item>
<el-form-item label="项目代号|名称" prop="name" v-if="opType!=='add'">
<el-input v-model="editForm.code" placeholder="项目代号,不可为空" style="width:20%;" ></el-input><el-input style="width:80%;" v-model="editForm.name" placeholder="" ></el-input>
<font color="blue" style="font-size:10px;">项目代号为合同上的项目代号甲乙方共享;项目内部编号为 &nbsp;代号-四位随机码</font>
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item label="项目类型" prop="xmType">
<el-select v-model="editForm.xmType">
<el-option v-for="(i,index) in dicts['projectType']" :label="i.name" :value="i.id" :key="index"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="优先级别" prop="priority">
<el-select v-model="editForm.priority">
<el-option v-for="(i,index) in dicts['priority']" :label="i.name" :value="i.id" :key="index"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="工作方式" prop="workType">
<el-radio label="1" v-model="editForm.workType">scrum</el-radio>
<el-radio label="2" v-model="editForm.workType">看板</el-radio>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="报工方式" prop="wtype">
<el-select v-model="editForm.wtype">
<el-option label="无须报工" value="0" ></el-option>
<el-option label="每日报工" value="1" ></el-option>
<el-option label="工期内任意日报工" value="2" ></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<el-form-item label="总控" prop="admUserid">
<el-form-item label="项目总控" prop="admUserid">
<el-input readonly v-model="editForm.admUsername" @click.native="showUserVisible('admUserid')"></el-input>
<font style="font-size:12px;" color="blue"></font>
</el-form-item>
@ -66,8 +96,29 @@
<el-input type="textarea" :rows="6" v-model="editForm.description" placeholder="项目描述" ></el-input>
</el-form-item>
</el-collapse-item>
<el-collapse-item title="工期及成本预估" name="2">
<el-form-item label="工期及成本预估" >
<el-collapse-item title="控制开关" name="2">
<el-form-item label="">
<el-form-item prop="budgetCtrl">
<el-checkbox v-model="editForm.budgetCtrl" true-label="1" false-label="0" >总预算控制</el-checkbox>
<font style="font-size:12px;" color="blue">开启后项目计划总预算大于项目总预算后将无法添加新的计划任务进行项目预算变更后方可继续添加计划任务</font>
</el-form-item>
<el-form-item label="" prop="budgetEarly">
<el-checkbox v-model="editForm.budgetEarly" true-label="1" false-label="0" >总预算超额预警</el-checkbox> &nbsp;&nbsp;<el-input v-if="editForm.budgetEarly" type="number" v-model="editForm.earlyAmt" placeholder="" style="width:20%;" ></el-input> &nbsp;
<br><font style="font-size:12px;" color="blue">一级计划总预算超出项目预算一定额度将进入超预算预警项目清单直到调小计划预算或者调大项目预算后解除</font>
</el-form-item>
<el-form-item label="" prop="phaseActCtrl">
<el-checkbox v-model="editForm.phaseActCtrl" true-label="1" false-label="0" >实际金额控制</el-checkbox>
<font style="font-size:12px;" color="blue">每条计划实际金额不能大于预算金额; 任务的实际金额合计不能大于与任务关联的上级计划的预算</font>
</el-form-item>
</el-form-item>
</el-collapse-item>
<el-collapse-item title="工期" name="3">
<el-row>
<span v-if="opType!=='add'" style="float:right;">
<el-button icon="el-icon-watch" type="warning" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_delay_approva'})">工期变更申请</el-button>
</span>
</el-row>
<el-form-item label="" >
<el-row>
<el-date-picker
v-model="dateRanger"
@ -83,43 +134,55 @@
:picker-options="pickerOptions"
></el-date-picker>
<el-input style="width:150px;" type="number" v-model="editForm.planWorkingHours" :precision="2" :step="8" :min="0" placeholder="预计工时"></el-input>小时 &nbsp;&nbsp;<el-tag>参考工时{{autoParams.weekday*8}}小时,工作日{{autoParams.weekday}}</el-tag>
<br>
<el-checkbox v-model="autoSet">工期变化自动更新预估成本/合同金额/预估工时等关联数据</el-checkbox>
</el-row>
</el-form-item>
</el-collapse-item>
<el-collapse-item title="成本预估" name="4">
<el-row>
<span v-if="opType!=='add'" style="float:right;">
<el-button icon="el-icon-edit" type="warning" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_budget_change_approva'})">预算变更申请</el-button>
</span>
</el-row>
<el-divider></el-divider>
<el-form-item label="" >
<el-row>
<el-col :span="4">人员类型</el-col>
<el-col :span="3">类型</el-col>
<el-col :span="4">人数</el-col>
<el-col :span="4">工作量</el-col>
<el-col :span="4">单价</el-col>
<el-col :span="6">工作量</el-col>
<el-col :span="3">单价</el-col>
<el-col :span="8">总价</el-col>
</el-row>
<el-divider></el-divider>
<el-row>
<el-col :span="4">内购</el-col>
<el-col :span="4"><el-input style="width:150px;" type="number" v-model="editForm.planIuserCnt" :precision="0" :step="1" :min="0" placeholder="内购人数"></el-input>
<el-col :span="3">内购</el-col>
<el-col :span="4"><el-input style="width:90%;" type="number" v-model="editForm.planIuserCnt" :precision="0" :step="1" :min="0" placeholder="内购人数"></el-input>
</el-col>
<el-col :span="4">{{autoParams.planIuserWorkload}}人时</el-col>
<el-col :span="4"><el-input style="width:150px;" type="number" v-model="editForm.planIuserPrice" :precision="0" :step="1" :min="0" placeholder="预计内部人时单价"></el-input> </el-col>
<el-col :span="6">{{autoParams.planIuserWorkload}}h</el-col>
<el-col :span="3"><el-input style="width:90%;" type="number" v-model="editForm.planIuserPrice" :precision="0" :step="1" :min="0" placeholder="预计内部h单价"></el-input> </el-col>
<el-col :span="8">{{this.toFixed(autoParams.planIuserAt)}},{{this.toFixed(autoParams.planIuserAt/10000)}} 万元</el-col>
</el-row>
<el-divider></el-divider>
<el-row>
<el-col :span="4">外购</el-col>
<el-col :span="4"><el-input style="width:150px;" type="number" v-model="editForm.planOuserCnt" :precision="0" :step="1" :min="0" placeholder="外购人数"></el-input>
<el-col :span="3">外购</el-col>
<el-col :span="4"><el-input style="width:90%;" type="number" v-model="editForm.planOuserCnt" :precision="0" :step="1" :min="0" placeholder="外购人数"></el-input>
</el-col>
<el-col :span="4">{{autoParams.planOuserWorkload}}人时</el-col>
<el-col :span="4"><el-input style="width:150px;" type="number" v-model="editForm.planOuserPrice" :precision="0" :step="1" :min="0" placeholder="预计外购人时单价"></el-input> </el-col>
<el-col :span="4">{{autoParams.planOuserAt }} {{autoParams.planOuserAt/10000 }}万元</el-col>
<el-col :span="6">{{autoParams.planOuserWorkload}}h</el-col>
<el-col :span="3"><el-input style="width:90%;" type="number" v-model="editForm.planOuserPrice" :precision="0" :step="1" :min="0" placeholder="预计外购h单价"></el-input> </el-col>
<el-col :span="8">{{autoParams.planOuserAt }} {{autoParams.planOuserAt/10000 }}万元</el-col>
</el-row>
<el-divider></el-divider>
<el-row>
<el-col :span="4">合计</el-col>
<el-col :span="4"> {{autoParams.planOuserCnt+autoParams.planIuserCnt}}
<el-col :span="3">合计</el-col>
<el-col :span="4"> {{autoParams.planOuserCnt+autoParams.planIuserCnt}}
</el-col>
<el-col :span="4">{{autoParams.planOuserWorkload+autoParams.planIuserWorkload }}人时,{{ (autoParams.planOuserWorkload+autoParams.planIuserWorkload)/8/20 }}人月 </el-col>
<el-col :span="4">平均{{ (parseFloat2(autoParams.planOuserPrice) + parseFloat2(autoParams.planIuserPrice))/2}}/人时</el-col>
<el-col :span="6">{{autoParams.planOuserWorkload+autoParams.planIuserWorkload }}h,{{ (autoParams.planOuserWorkload+autoParams.planIuserWorkload)/8/20 }}人月 </el-col>
<el-col :span="3"> {{ (parseFloat2(autoParams.planOuserPrice) + parseFloat2(autoParams.planIuserPrice))/2}}/h</el-col>
<el-col :span="8">{{autoParams.planTotalCost}} {{(autoParams.planTotalCost)/10000}} 万元</el-col>
</el-row>
</el-form-item>
@ -134,31 +197,31 @@
合计 <el-input style="width:150px;" disabled type="number" v-model="editForm.planTotalCost" :precision="2" :step="1000" :min="0" placeholder="总成本预算"></el-input> <el-tag> {{this.toFixed(autoParams.planTotalCost/10000)}}万元</el-tag>
</el-row>
</el-form-item>
<el-form-item label="收入及盈利水平预估">
<el-row>
预计收款总额<el-input style="width:150px;" type="number" v-model="editForm.totalReceivables" :precision="2" :step="1000" :min="0" disabled placeholder="预计总收款金额"></el-input> <el-tag> {{this.toFixed(autoParams.totalReceivables/10000)}}万元</el-tag>
合同总金额 <el-input style="width:150px;" type="number" v-model="editForm.contractAmt" :precision="2" :step="1000" :min="0" placeholder="合同总金额"></el-input> <el-tag>{{this.toFixed(autoParams.contractAmt/10000)}}万元</el-tag>
</el-row>
<el-row>
税率<el-input style="width:150px;" type="number" v-model="editForm.taxRate" :precision="2" :step="0.01" :min="0" :max="0.99" placeholder="税率"></el-input>
考核标准毛利率<el-input style="width:150px;" type="number" v-model="editForm.budgetMarginRate" :precision="2" :step="0.01" :min="0" :max="0.99" placeholder="毛利率"></el-input>
当前毛利率为<el-tag>{{toFixed(parseFloat2(autoParams.currentBudgetMarginRate)*100,2)}}%</el-tag>
</el-row>
</el-form-item>
</el-collapse-item>
<el-collapse-item title="收入及盈利水平" name="5">
<el-form-item label="">
<el-row>
税率<el-input style="width:150px;" type="number" v-model="editForm.taxRate" :precision="2" :step="5" :min="0" :max="100" placeholder="税率"></el-input> %
考核标准毛利率<el-input style="width:150px;" type="number" v-model="editForm.budgetMarginRate" :precision="2" :step="5" :min="0" :max="100" placeholder="毛利率"></el-input>%
当前预估毛利率为<el-tag>{{toFixed(parseFloat2(autoParams.currentBudgetMarginRate),2)}}%</el-tag>
</el-row>
<el-row>
预计收\付款总额<el-input style="width:150px;" type="number" v-model="editForm.totalReceivables" :precision="2" :step="1000" :min="0" disabled placeholder="预计总收款金额"></el-input> <el-tag> {{this.toFixed(autoParams.totalReceivables/10000)}}万元</el-tag>
合同总金额 <el-input style="width:150px;" type="number" v-model="editForm.contractAmt" :precision="2" :step="1000" :min="0" placeholder="合同总金额"></el-input> <el-tag>{{this.toFixed(editForm.contractAmt/10000)}}万元</el-tag>
</el-row>
</el-form-item>
</el-collapse-item>
</el-collapse>
</el-form>
</el-row>
<el-row>
<el-button v-loading="load.edit" type="primary" @click.native="editSubmit" :disabled="load.edit==true">提交</el-button>
<el-button icon="el-icon-watch" type="danger" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_baseinfo_change_approva'})">基本信息修改申请</el-button>
<el-button icon="el-icon-watch" type="danger" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_delay_approva'})">延期申请</el-button>
<el-button icon="el-icon-star-on" type="success" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_start_approva'})">立项申请</el-button>
<el-button icon="el-icon-success" type="success" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_over_approva'})">结项申请</el-button>
<el-button icon="el-icon-edit" type="warning" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_budget_change_approva'})">预算变更申请</el-button>
<el-button icon="el-icon-video-pause" type="danger" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_pause_approva'})">项目暂停申请</el-button>
<el-button icon="el-icon-video-play" type="primary" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_restart_approva'})">项目重新启动申请</el-button>
<span v-if="opType!=='add'" style="float:right;">
<el-button icon="el-icon-star-on" type="success" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_start_approva'})">立项申请</el-button>
<el-button icon="el-icon-success" type="success" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_over_approva'})">结项申请</el-button>
<el-button icon="el-icon-video-pause" type="info" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_pause_approva'})">项目暂停申请</el-button>
<el-button icon="el-icon-video-play" type="primary" @click="handleCommand({type:'sendToProcessApprova',data:editForm,bizKey:'xm_project_restart_approva'})">项目重新启动申请</el-button>
</span>
</el-row>
<el-drawer append-to-body title="选择员工" :visible.sync="userSelectVisible" size="60%">
@ -174,7 +237,7 @@
import config from "@/common/config"; //
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { editXmProject,getDefOptions } from '@/api/xm/core/xmProject';
import { addXmProject,editXmProject,getDefOptions,createProjectCode } from '@/api/xm/core/xmProject';
import { uploadBase64 } from '@/api/mdp/arc/image';
import { mapGetters } from 'vuex';
@ -217,14 +280,14 @@
planNouserAt=0.0
}
if(budgetMarginRate==null || budgetMarginRate==''){
budgetMarginRate=0.4
budgetMarginRate=13
}
if(planWorkingHours==null || planWorkingHours==''){
planWorkingHours=0.0
}
if(taxRate==null || taxRate==''){
taxRate=0.03
taxRate=6
}
var autoParams={
@ -252,13 +315,13 @@
autoParams.planNouserAt= planNouserAt
autoParams.budgetMarginRate=budgetMarginRate
autoParams.planTotalCost= autoParams.planOuserAt + autoParams.planIuserAt + autoParams.planNouserAt
autoParams.totalReceivables=autoParams.planTotalCost/(1-budgetMarginRate)/ (1-taxRate)
autoParams.totalReceivables=autoParams.planTotalCost/(100-budgetMarginRate)*100/ (100-taxRate)*100
autoParams.contractAmt =autoParams.totalReceivables
var totalReceivables=this.editForm.totalReceivables
if(totalReceivables==null || totalReceivables=='' || isNaN(totalReceivables)){
autoParams.currentBudgetMarginRate=-99
}else{
autoParams.currentBudgetMarginRate= this.toFixed(1-this.editForm.planTotalCost/(this.editForm.totalReceivables* (1-taxRate)),4)
autoParams.currentBudgetMarginRate= this.toFixed(1-this.editForm.planTotalCost/(this.editForm.totalReceivables* (100-taxRate)),4)
}
// 1.=-/×100%=/×100%
@ -296,12 +359,11 @@
}
},
},
props:['selProject','visible'],
props:['selProject','visible','xmProject','opType'/**add、edit */],
watch: {
'visible':function(visible) {
if(visible==true){
this.editForm=Object.assign({},this.selProject)
this.dateRanger=[this.editForm.startTime,this.editForm.endTime]
this.initData();
}
},
'planTotalAt':{
@ -315,40 +377,46 @@
//this.editForm.budgetMarginRate=this.toFixed((this.editForm.totalReceivables-this.editForm.planTotalCost)/this.editForm.totalReceivables,4)
},
autoParams(){
this.fillPlanWorkingHoursToField()
this.fillPlanCostAtToField();
this.fillTotalReceivablesToField();
this.fillBudgetMarginRateToField()
if(this.autoSet){
this.fillPlanWorkingHoursToField()
this.fillPlanCostAtToField();
this.fillTotalReceivablesToField();
this.fillBudgetMarginRateToField()
}
},
editForm:{
handler(newValue, oldValue) {
if(this.opType==='add'){
return;
}
this.$notify.closeAll();
this.changeTips=[];
if(this.selProject.planWorkingHours!=this.editForm.planWorkingHours){
var distance=this.selProject.planWorkingHours-this.editForm.planWorkingHours
var operType=distance>0?"-":"+";
this.changeTips.push("预计总工期: "+ this.selProject.planWorkingHours+" > " +this.editForm.planWorkingHours+"&nbsp;&nbsp;&nbsp;<strong>"+operType+Math.abs(distance).toFixed(2)+"</strong>小时");
this.changeTips.push("预计总工期: "+ this.selProject.planWorkingHours+" ==> " +this.editForm.planWorkingHours+"&nbsp;&nbsp;&nbsp;<strong>"+operType+Math.abs(distance).toFixed(2)+"</strong>小时");
}
if(this.selProject.planTotalCost!=this.editForm.planTotalCost){
var distance=this.selProject.planTotalCost-this.editForm.planTotalCost
var operType=distance>0?"-":"+";
this.changeTips.push("预计总成本: "+ this.selProject.planTotalCost+" > " +this.editForm.planTotalCost+"&nbsp;&nbsp;&nbsp;<strong>"+operType+Math.abs(distance).toFixed(2)+"</strong>元");
this.changeTips.push("预计总成本: "+ this.selProject.planTotalCost+" ==> " +this.editForm.planTotalCost+"&nbsp;&nbsp;&nbsp;<strong>"+operType+Math.abs(distance).toFixed(2)+"</strong>元");
}
if(this.selProject.budgetMarginRate!=this.editForm.budgetMarginRate){
var distance=this.selProject.budgetMarginRate-this.editForm.budgetMarginRate
var operType=distance>0?"-":"+";
this.changeTips.push("毛利率: "+ this.selProject.budgetMarginRate+" > " +this.editForm.budgetMarginRate+"&nbsp;&nbsp;&nbsp;<strong>"+operType+Math.abs(distance).toFixed(2)+"</strong>%");
this.changeTips.push("毛利率: "+ this.selProject.budgetMarginRate+" ==> " +this.editForm.budgetMarginRate+"&nbsp;&nbsp;&nbsp;<strong>"+operType+Math.abs(distance).toFixed(2)+"</strong>%");
}
if(this.selProject.totalReceivables!=this.editForm.totalReceivables){
var distance=this.selProject.totalReceivables-this.editForm.totalReceivables
var operType=distance>0?"-":"+";
this.changeTips.push("预计总收款: "+ this.selProject.totalReceivables+" > " +this.editForm.totalReceivables+"&nbsp;&nbsp;&nbsp;<strong>"+operType+Math.abs(distance).toFixed(2)+"</strong>元");
this.changeTips.push("预计总收款: "+ this.selProject.totalReceivables+" ==> " +this.editForm.totalReceivables+"&nbsp;&nbsp;&nbsp;<strong>"+operType+Math.abs(distance).toFixed(2)+"</strong>元");
}
if(this.selProject.contractAmt!=this.editForm.contractAmt){
var distance=this.selProject.contractAmt-this.editForm.contractAmt
var operType=distance>0?"-":"+";
this.changeTips.push("合同金额: "+ this.selProject.contractAmt+" > " +this.editForm.contractAmt+"&nbsp;&nbsp;&nbsp;<strong>"+operType+Math.abs(distance).toFixed(2)+"</strong>元");
this.changeTips.push("合同金额: "+ this.selProject.contractAmt+" ==> " +this.editForm.contractAmt+"&nbsp;&nbsp;&nbsp;<strong>"+operType+Math.abs(distance).toFixed(2)+"</strong>元");
}
if(this.changeTips.length==0){
@ -376,17 +444,20 @@
load:{ list: false, add: false, del: false, edit: false },//...
editFormRules: {
name: [{
required: true, message: '项目名称不可为空' , trigger: 'blur'
required: true, message: '项目名称不可为空' , trigger: 'change'
}],
code: [{
required: true, message: '项目代号不可为空', trigger: 'blur'
required: true, message: '项目代号不可为空', trigger: 'change'
}],
xmType: [{
required: true, message: '项目类型不可为空', trigger: 'change'
}],
xmType: [{
required: true, message: '项目类型不可为空', trigger: 'blur'
required: true, message: '项目类型不可为空', trigger: 'change'
}],
priority: [{
required: true, message: '优先级不可为空', trigger: 'blur'
required: true, message: '优先级不可为空', trigger: 'change'
}],
admUserid: [{
required: true, message: '项目总控不能为空', trigger: 'change'
@ -412,6 +483,7 @@
changeTips:[],//
maxTableHeight:300,
currUserType:'',
autoSet:false,
/**end 在上面加自定义属性**/
}//end return
},//end data
@ -435,14 +507,11 @@
},
//XmProject xm_project@submit="afterEditSubmit"
editSubmit: function () {
if(!this.roles.some(i=>i.roleid=='projectAdmin')){
this.$notify({showClose: true, message: "只有项目经理可以修改项目", type: 'error' });
return;
}
if("0" != this.selProject.status){
if(this.opType!=='add' && "0" != this.selProject.status){
this.$notify({showClose: true, message: "只有初始状态的项目可以修改,如确实需要修改,请进行项目变更审批", type: 'error' });
return;
}
var msg=this.xmProduct&&this.xmProduct.id?'将自动关联产品【'+this.xmProduct.productName+'】':'';
if (
this.dateRanger != null &&
this.dateRanger.length == 2
@ -455,13 +524,17 @@
}
this.$refs.editForm.validate((valid) => {
if (valid) {
this.$confirm('确认提交吗?', '提示', {}).then(() => {
this.$confirm('确认提交吗?'+msg, '提示', {}).then(() => {
this.load.edit=true
var func=editXmProject;
if(this.opType==='add'){
func=addXmProject;
}
let params = Object.assign({}, this.editForm);
params.planIuserWorkload=this.autoParams.planIuserWorkload
params.planOuserWorkload=this.autoParams.planOuserWorkload
params.planWorkload=this.autoParams.planWorkload
editXmProject(params).then((res) => {
func(params).then((res) => {
this.load.edit=false;
var tips=res.data.tips;
if(tips.isOk){
@ -728,6 +801,44 @@
},
createProjectCode(){
createProjectCode({}).then(res=>{
var tips=res.data.tips;
if(tips.isOk){
this.editForm.code=res.data.data
}
this.$notify({showClose: true, message: tips.msg, type: tips.isOk?'success':'error' });
})
},
initData(){
this.editForm={...this.selProject}
if(this.opType==='add'){
this.editForm.pmUserid=this.userInfo.userid
this.editForm.pmUsername=this.userInfo.username
this.editForm.admUserid=this.userInfo.userid
this.editForm.admUsername=this.userInfo.username
this.editForm.assUserid=this.userInfo.userid
this.editForm.assUsername=this.userInfo.username
this.editForm.status="0"
this.editForm.wtype=this.editForm.wtype||"2"
this.editForm.workType=this.editForm.workType||"1"
this.editForm.xmType=this.editForm.xmType||"2"
this.editForm.priority=this.editForm.priority||"2"
this.editForm.locked=this.editForm.locked||"0"
this.editForm.showOut=this.editForm.showOut||"2"
this.editForm.isTpl=this.editForm.isTpl||"0"
this.editForm.phaseActCtrl=this.editForm.phaseActCtrl||"1";
this.editForm.budgetEarly=this.editForm.budgetEarly||"1";
this.editForm.earlyAmt=this.editForm.earlyAmt||-10000;
this.editForm.budgetCtrl=this.editForm.budgetCtrl||"0";
this.editForm.taxRate=this.editForm.taxRate||6
this.editForm.budgetMarginRate=this.editForm.budgetMarginRate||13
this.autoSet=true;
}else{
this.dateRanger=[this.editForm.startTime,this.editForm.endTime]
this.autoSet=false;
}
}
/**end 在上面加自定义方法**/
},//end method
components: { html2canvas,UsersSelect,
@ -735,10 +846,7 @@
},
mounted() {
this.maxTableHeight=util.calcTableMaxHeight(this.$refs.table.$el)-20;
this.editForm=Object.assign({},this.selProject);
this.dateRanger=[this.editForm.startTime,this.editForm.endTime]
this.initData();
initSimpleDicts('all',['projectType','priority','projectStatus']).then(res=>{
this.dicts=res.data.data;
})

10
src/views/xm/core/xmProject/XmProjectForLink.vue

@ -5,9 +5,9 @@
<el-input v-model="filters.key" style="width:30%;" placeholder="请输入关键字进行查找项目" v-if="!xmIteration && !xmProduct">
</el-input>
<el-button @click="searchXmProjects" icon="el-icon-search" v-if="!xmIteration && !xmProduct"></el-button>
<el-button icon="el-icon-plus" @click="xmProjectListVisible=true" v-if="!xmIteration">
更多项目到产品中
</el-button>
<xm-project-select @row-click="onXmProjectSelect">
<font slot="title">加更多项目到产品中</font>
</xm-project-select>
</el-row>
<el-row class="page-main ">
<el-table ref="table" :height="tableHeight" stripe :data="xmProjects" highlight-current-row v-loading="load.list" style="width: 100%;">
@ -43,7 +43,7 @@
import { listXmProject, } from '@/api/xm/core/xmProject';
import { mapGetters } from 'vuex'
import { delXmProductProjectLink, addXmProductProjectLink,batchDelXmProductProjectLink } from '@/api/xm/core/xmProductProjectLink';
import XmProjectList from './XmProjectList.vue';
import XmProjectSelect from '@/views/xm/core/components/XmProjectSelect.vue';
@ -206,7 +206,7 @@ import XmProjectList from './XmProjectList.vue';
},//end methods
components: {
XmProjectList
XmProjectSelect
//
},

18
src/views/xm/core/xmProject/XmProjectForLinkComplex.vue

@ -5,13 +5,7 @@
<el-tabs type="border-card" :value="showPanel" @tab-click="tabClick">
<el-tab-pane disabled>
<div slot="label">
<el-popover
placement="bottom"
width="400"
trigger="click">
<xm-project-select ref="xmProjectSelect" :auto-select="true" :xm-iteration="xmIteration" :xm-product="xmProduct" @row-click="onProjectRowClick" @clear-select="onProjectClearSelect"></xm-project-select>
<el-link type="warning" slot="reference" icon="el-icon-search"><font style="font-size:14px;">{{selProject?selProject.name:'选择项目'}}</font></el-link>
</el-popover>
<xm-project-select ref="xmProjectSelect" :auto-select="true" :link-iteration-id="xmIteration?xmIteration.id:null" :link-product-id="xmProduct?xmProduct.id:null" @row-click="onProjectRowClick" @clear-select="onProjectClearSelect"></xm-project-select>
</div>
</el-tab-pane>
@ -23,7 +17,7 @@
v-model="projectAddVisible"
trigger="manual">
<xm-project-add :visible="projectAddVisible" :xm-product="xmProduct" @cancel="projectAddVisible=false" @submit="afterProjectAddSubmit"></xm-project-add>
<xm-project-add :visible="projectAddVisible" op-type="add" :xm-product="xmProduct" @cancel="projectAddVisible=false" @submit="afterProjectAddSubmit"></xm-project-add>
<el-link type="warning" slot="reference" @click="projectAddVisible=true" icon="el-icon-plus"><font style="font-size:14px;">项目</font></el-link>
</el-popover>
@ -35,7 +29,7 @@
<el-tab-pane label="项目详情" name="detail" v-if="selProject&&selProject.id">
<xm-project-detail v-if="showPanel=='detail'" :sel-project="selProject" @submit="afterEditSubmit"></xm-project-detail>
</el-tab-pane>
<el-tab-pane label="配置关联的产品" name="productProjectLink" v-if="selProject&&selProject.id" >
<el-tab-pane label="配置关联的产品" name="productProjectLink" v-if="selProject&&selProject.id && !xmProduct" >
<xm-product-project-link-mng v-if="showPanel=='productProjectLink'" :sel-project="selProject"></xm-product-project-link-mng>
</el-tab-pane>
<!--
@ -74,14 +68,14 @@
import XmProductMng from '../xmProduct/XmProductMng.vue';
import XmTaskMng from '../xmTask/XmTaskMng.vue';
import XmQuestionMng from '../xmQuestion/XmQuestionMng.vue';
import XmProjectSelect from './XmProjectSelect.vue';
import XmProjectSelect from '@/views/xm/core/components/XmProjectSelect.vue';
import XmProjectForLink from './XmProjectForLink.vue';
import XmProductSelect from '../xmProduct/XmProductSelect.vue';
import XmProductSelect from '@/views/xm/core/components/XmProductSelect.vue'
import XmProductProjectForLink from '../xmProduct/XmProductProjectForLink.vue';
import XmProjectOverview from "./XmProjectOverview";
import XmProjectAdd from './XmProjectAdd';//
import XmProjectAdd from './XmProjectEdit';//
import XmProjectDetail from './XmProjectDetail';//
import XmProductProjectLinkMng from '../xmProductProjectLink/XmProductProjectLinkMng.vue';

3
src/views/xm/core/xmProject/XmProjectInfo.vue

@ -162,9 +162,6 @@
import util from '@/common/js/util';//
//import Sticky from '@/components/Sticky' // header
//import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmProject,editStatus , delXmProject, batchDelXmProject } from '@/api/xm/core/xmProject';
import XmProjectAdd from './XmProjectAdd';//
import XmProjectEdit from './XmProjectEdit';//
import { mapGetters } from 'vuex';
import xmTaskMng from '../xmTask/XmTaskMng';
import xmGroupMng from '../xmGroup/XmGroupMng';

293
src/views/xm/core/xmProject/XmProjectList.vue

@ -1,293 +0,0 @@
<template>
<section class="padding">
<el-row>
<el-input v-model="filters.key" style="width:60%;" placeholder="项目名称模糊查询">
</el-input>
<el-button @click="searchXmProjects" icon="el-icon-search"></el-button>
</el-row>
<el-row class="page-main ">
<el-table ref="table" :height="tableHeight" stripe :data="xmProjects" highlight-current-row v-loading="load.list" style="width: 100%;">
<el-table-column type="index" label="序号" width="55" ></el-table-column>
<el-table-column prop="id" label="项目编码" min-width="80" ></el-table-column>
<el-table-column prop="name" label="项目名称" min-width="120" ></el-table-column>
<el-table-column label="操作" width="100" fixed="right">
<template slot-scope="scope">
<el-button-group>
<el-button type="primary" @click.stop="selectProject(scope.row)" >选中</el-button>
</el-button-group>
<!-- <el-button style="width:100%;" slot="reference" class="see-more" type="text" icon="el-icon-more"></el-button>
</el-popover> -->
</template>
</el-table-column>
</el-table>
<el-pagination layout="total, sizes, prev, pager, 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 Vue from 'vue'
import util from '@/common/js/util';//
//import Sticky from '@/components/Sticky' // header
import config from "@/common/config"; //
//import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmProject, } from '@/api/xm/core/xmProject';
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters([
'userInfo','roles'
]),
},
data() {
return {
filters: {
key: ''
},
xmProjects: [],//
pageInfo:{//
total:0,//0>0
pageSize:10,//
count:false,//
pageNum:1,//1
orderFields:['create_time'],// ['sex','student_id']
orderDirs:['desc']// asc,desc ['asc','desc']
},
load:{ list: false, edit: false, del: false, add: false },//...
sels: [],//
dicts:{},// params=[{categoryId:'0001',itemCode:'sex'}] {'sex':[{optionValue:'1',optionName:'',seqOrder:'1',fp:'',isDefault:'0'},{optionValue:'2',optionName:'',seqOrder:'2',fp:'',isDefault:'0'}]}
addFormVisible: false,//xmProject
//xmProject
addForm: {
id:'',code:'',name:'',xmType:'',startTime:'',endTime:'',urgent:'',priority:'',description:'',createUserid:'',createUsername:'',createTime:'',assess:'',assessRemarks:'',status:'',branchId:'',planTotalCost:'',bizProcInstId:'',bizFlowState:'',planNouserAt:'',planIuserAt:'',planOuserAt:'',locked:'',baseTime:'',baseRemark:'',baselineId:'',planWorkload:'',totalReceivables:'',budgetMarginRate:'',contractAmt:'',planIuserPrice:'',budgetOuserPrice:'',planOuserCnt:'',planIuserCnt:'',planWorkingHours:''
},
editFormVisible: false,//
tableHeight:300,
//xmProject
editForm: {
id:'',code:'',name:'',xmType:'',startTime:'',endTime:'',urgent:'',priority:'',description:'',createUserid:'',createUsername:'',createTime:'',assess:'',assessRemarks:'',status:'',branchId:'',planTotalCost:'',bizProcInstId:'',bizFlowState:'',planNouserAt:'',planIuserAt:'',planOuserAt:'',locked:'',baseTime:'',baseRemark:'',baselineId:'',planWorkload:'',totalReceivables:'',budgetMarginRate:'',contractAmt:'',planIuserPrice:'',budgetOuserPrice:'',planOuserCnt:'',planIuserCnt:'',planWorkingHours:''
},
/**end 自定义属性请在上面加 请加备注**/
}
},//end data
methods: {
handleSizeChange(pageSize) {
this.pageInfo.pageSize=pageSize;
this.getXmProjects();
},
handleCurrentChange(pageNum) {
this.pageInfo.pageNum = pageNum;
this.getXmProjects();
},
// 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.getXmProjects();
},
searchXmProjects(){
this.pageInfo.count=true;
this.getXmProjects();
},
// XmProject xm_project
getXmProjects() {
let params = {
pageSize: this.pageInfo.pageSize,
pageNum: this.pageInfo.pageNum,
total: this.pageInfo.total,
count:this.pageInfo.count,
};
if(this.filters.key){
params.key='%'+this.filters.key+'%'
}
this.load.list = true;
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.branchId = this.userInfo.branchId;
listXmProject(params).then((res) => {
var tips=res.data.tips;
if(tips.isOk){
console.log(res.data);
this.pageInfo.total = res.data.total;
this.pageInfo.count=false;
this.xmProjects = res.data.data;
}else{
this.$notify({showClose: true, message: tips.msg, type: 'error' });
}
this.load.list = false;
}).catch( err => this.load.list = false );
},
selectProject:function(row){
this.editForm=row
this.$emit('project-confirm',this.editForm);
}
/**end 自定义函数请在上面加**/
},//end methods
components: {
//
},
mounted() {
this.$nextTick(() => {
this.tableHeight = util.calcTableMaxHeight(this.$refs.table.$el);
this.showInfo = false;
this.getXmProjects();
});
}
}
</script>
<style scoped>
* >>> .sub-navbar{
background: #fafbfc;
}
.changebtn{
float: right;
padding: 0 10px;
display: flex;
align-items: center;
line-height: 0;
height: 100%;
}
.changebtn > button{
padding: 0;
border: 0;
color: #333;
}
.changebtn >>> i::before{
font-size:20px;
}
.changebtn-active{
color: #409EFF !important;
}
.app-container{
padding: 10px;
}
.el-menu-demo{
border: 0 !important;
height: 50px;
background-color: #fafbfc;
}
.el-menu-demo>.el-menu-item,
.el-menu-demo>.el-submenu >>> .el-submenu__title{
height: 100%;
line-height: 50px;
color: #909399;
}
.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus,
.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover,
.el-menu--horizontal>.el-submenu .el-submenu__title:hover{
background-color: transparent;
}
.project-card{
font-size: 12px;
color: #999;
margin: 10px 12px;
}
.project-card:hover{
border-color: #00abfc;
}
.project-card >>> .el-card__body{
padding: 20px 15px 10px;
}
.project-name{
font-size: 16px;
font-weight: 700;
color: #333;
height: 24px;
}
.project-id{
margin-top: 4px;
height: 18px;
}
.project-info{
display: flex;
margin-top: 8px;
}
.project-info>div{
display: flex;
flex-direction: column;
}
.info-item{
width: 15%;
text-align: center;
}
.info-item >>> span{
display: block;
}
.item-total{
font-size: 18px;
color: #666;
}
.info-task{
padding-left: 20px;
width: 70%;
border-left: 1px solid #efefef;
}
.finish-task{
color: #00abfc !important;
}
.project-rate{
margin: 15px 0;
}
.project-rate>.el-progress{
display: flex;
align-items: center;
}
.project-rate >>> .el-progress-bar{
padding-right: 0;
margin-right: 0;
}
.project-rate >>> .el-progress__text{
margin-left: 5px;
}
.project-footer{
display: flex;
}
.project-footer>div{
width: 30%;
}
.project-footer>div:not(:first-child){
width: 70%;
}
.project-period{
text-align: right;
}
.see-more > i{
background:#000;
}
/* 超过宽度则用...代替 */
.truncate{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
[v-cloak]{
display: none;
}
</style>

24
src/views/xm/core/xmProject/XmProjectMng.vue

@ -8,6 +8,7 @@
</el-col>
<el-col :span="templateVisible?18:24" class="border padding-top padding-right">
<el-row class="padding-left">
<xm-product-select style="display:inline;" class="hidden-md-and-down" :auto-select="false" @row-click="onProductSelected" @clear-select="onProductClose"></xm-product-select>
<el-select v-model="menukey" @change="handleSelect" clearable>
<el-option value="all" label="全部"></el-option>
<el-option value="compete" label="我参与"></el-option>
@ -28,8 +29,8 @@
<el-select v-model="filters.status" clearable placeholder="项目状态">
<el-option v-for="(item,index) in dicts['projectStatus']" :value="item.id" :label="item.name" :key="index"></el-option>
</el-select>
<el-input class="hidden-md-and-down" placeholder="选择产品" v-model="filters.productName" @click.native="productSelectVisible=true" clearable @clear="onProductClose" style="width:15%;"></el-input>
<el-input v-model="filters.key" style="width:15%;" placeholder="项目名称模糊查询" clearable>
<el-input v-model="filters.key" style="width:15%;" placeholder="项目名称模糊查询" clearable>
</el-input>
<el-button style="margin-top: 10px;" type="primary" icon="el-icon-search" @click="searchXmProjects">查询</el-button>
<el-popover
@ -256,10 +257,10 @@
</el-row>
<el-drawer title="项目新增" :visible.sync="addFormVisible" :with-header="false" size="60%" :close-on-click-modal="false" append-to-body>
<xm-project-add :sel-project="addForm" :visible="addFormVisible" @cancel="addFormVisible=false" @submit="afterAddSubmit"></xm-project-add>
<xm-project-add :sel-project="addForm" op-type="add" :visible="addFormVisible" @cancel="addFormVisible=false" @submit="afterAddSubmit"></xm-project-add>
</el-drawer>
<el-drawer title="项目编辑" :visible.sync="editFormVisible" :with-header="false" size="60%" :close-on-click-modal="false" append-to-body>
<xm-project-edit :sel-project="editForm" :visible="editFormVisible" @cancel="editFormVisible=false" @submit="afterEditSubmit"></xm-project-edit>
<xm-project-edit :sel-project="editForm" op-type="edit" :visible="editFormVisible" @cancel="editFormVisible=false" @submit="afterEditSubmit"></xm-project-edit>
</el-drawer>
<el-drawer :title="selectProject==null?'项目明细':selectProject.name" center :fullscreen="true" :visible.sync="showInfo" size="50%" :close-on-click-modal="false" append-to-body>
<xm-project-info :sel-project="selectProject" :visible="showInfo" @changeShowInfo="changeShowInfo" @submit="changeShowInfo"></xm-project-info>
@ -302,13 +303,6 @@
<el-button type="primary" @click="onCopyToConfirm" :disabled="load.add" v-loading="load.add"> </el-button>
</span>
</el-dialog>
<el-drawer
append-to-body
title="产品"
:visible.sync="productSelectVisible"
width="80%">
<xm-product-mng :is-select-product="true" @selected="onProductSelected"></xm-product-mng>
</el-drawer>
</section>
</template>
@ -323,13 +317,13 @@
import { loadTasksToXmProjectState , loadTasksSettleToXmProjectState} from '@/api/xm/core/xmProjectState';
import { addXmMyFocus , delXmMyFocus } from '@/api/xm/core/xmMyFocus';
import XmProjectAdd from './XmProjectAdd';//
import XmProjectAdd from './XmProjectEdit';//
import XmProjectEdit from './XmProjectEdit';//
import { mapGetters } from 'vuex'
import xmTaskMng from '../xmTask/XmTaskMng';
import xmProjectInfo from './XmProjectInfo';
import XmProjectTplMng from './XmProjectTplMng';
import XmProductMng from '../xmProduct/XmProductSelect';
import XmProductSelect from '@/views/xm/core/components/XmProductSelect';
if(!Vue.component("xm-project-info")){
@ -475,7 +469,7 @@
params = this.menuFilter(params);
if(this.filters.productId){
params.productId = this.filters.productId
params.linkProductId = this.filters.productId
}
if(this.filters.status){
params.status = this.filters.status
@ -866,7 +860,7 @@
'xm-project-add':XmProjectAdd,
'xm-project-edit':XmProjectEdit,
XmProductMng,
XmProductSelect,
xmTaskMng,
XmProjectTplMng,
//

2
src/views/xm/core/xmProject/XmProjectOverviewComplex.vue

@ -95,7 +95,7 @@ export default {
}).catch( err => this.load.calcProject=false );
},
afterFlowSubmit(){
debugger;
listXmProject({id:this.selProject.id}).then(res=>{
var tips = res.data.tips;
if(tips.isOk){

198
src/views/xm/core/xmProject/XmProjectSelect.vue

@ -1,198 +0,0 @@
<template>
<section>
<el-row class="page-main padding-left">
<el-table ref="table" border :height="maxTableHeight" stripe :data="xmProjects" highlight-current-row v-loading="load.list" @selection-change="selsChange" @row-click="rowClick" style="width: 100%;" >
<el-table-column type="index" label="序号" >
</el-table-column>
<el-table-column prop="name" label="项目名称" >
<template slot="header">
项目名称 <el-button type="text" @click="clearSelect">清空所选</el-button><el-button type="text" @click="close">关闭</el-button>
</template>
<template slot-scope="scope">
{{scope.row.name}}&nbsp;&nbsp;
<font :color="scope.row.totalProgress==100?'green':'#FF8C00'">{{parseInt(scope.row.totalProgress)}}%</font>
</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 Vue from 'vue'
import util from '@/common/js/util';//
//import Sticky from '@/components/Sticky' // header
import config from "@/common/config"; //
//import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmProject, } from '@/api/xm/core/xmProject';
import { mapGetters } from 'vuex'
export default {
props:["xmIteration","xmProduct",'autoSelect'],
computed: {
...mapGetters([
'userInfo','roles'
]),
},
watch:{
"xmIteration.id":function(val){
this.getXmProjects();
},
"xmProduct.id":function(val){
this.getXmProjects();
}
},
data() {
return {
filters: {
key: ''
},
xmProjects: [],//
pageInfo:{//
total:0,//0>0
pageSize:10,//
count:false,//
pageNum:1,//1
orderFields:['create_time'],// ['sex','student_id']
orderDirs:['desc']// asc,desc ['asc','desc']
},
load:{ list: false, edit: false, del: false, add: false },//...
sels: [],//
dicts:{},// params=[{categoryId:'0001',itemCode:'sex'}] {'sex':[{optionValue:'1',optionName:'',seqOrder:'1',fp:'',isDefault:'0'},{optionValue:'2',optionName:'',seqOrder:'2',fp:'',isDefault:'0'}]}
addFormVisible: false,//xmProject
//xmProject
addForm: {
id:'',code:'',name:'',xmType:'',startTime:'',endTime:'',urgent:'',priority:'',description:'',createUserid:'',createUsername:'',createTime:'',assess:'',assessRemarks:'',status:'',branchId:'',planTotalCost:'',bizProcInstId:'',bizFlowState:'',planNouserAt:'',planIuserAt:'',planOuserAt:'',locked:'',baseTime:'',baseRemark:'',baselineId:'',planWorkload:'',totalReceivables:'',budgetMarginRate:'',contractAmt:'',planIuserPrice:'',budgetOuserPrice:'',planOuserCnt:'',planIuserCnt:'',planWorkingHours:''
},
editFormVisible: false,//
maxTableHeight:300,
//xmProject
editForm: {
id:'',code:'',name:'',xmType:'',startTime:'',endTime:'',urgent:'',priority:'',description:'',createUserid:'',createUsername:'',createTime:'',assess:'',assessRemarks:'',status:'',branchId:'',planTotalCost:'',bizProcInstId:'',bizFlowState:'',planNouserAt:'',planIuserAt:'',planOuserAt:'',locked:'',baseTime:'',baseRemark:'',baselineId:'',planWorkload:'',totalReceivables:'',budgetMarginRate:'',contractAmt:'',planIuserPrice:'',budgetOuserPrice:'',planOuserCnt:'',planIuserCnt:'',planWorkingHours:''
},
/**end 自定义属性请在上面加 请加备注**/
}
},//end data
methods: {
handleSizeChange(pageSize) {
this.pageInfo.pageSize=pageSize;
this.getXmProjects();
},
handleCurrentChange(pageNum) {
this.pageInfo.pageNum = pageNum;
this.getXmProjects();
},
// 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.getXmProjects();
},
//xmProject
selsChange: function (sels) {
this.sels = sels;
},
searchXmProjects(){
this.pageInfo.count=true;
this.getXmProjects();
},
rowClick(row){
this.editForm=row;
this.$emit("row-click",row);
},
// XmProject xm_project
getXmProjects() {
let params = {
pageSize: this.pageInfo.pageSize,
pageNum: this.pageInfo.pageNum,
total: this.pageInfo.total,
count:this.pageInfo.count,
};
if(this.filters.key){
params.key='%'+this.filters.key+'%'
}
this.load.list = true;
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(",")
}
if(this.xmIteration&&this.xmIteration.id){
params.iterationId=this.xmIteration.id
}
if(this.xmProduct&&this.xmProduct.id){
params.productId=this.xmProduct.id
}
params.branchId = this.userInfo.branchId;
listXmProject(params).then((res) => {
var tips=res.data.tips;
if(tips.isOk){
this.pageInfo.total = res.data.total;
this.pageInfo.count=false;
this.xmProjects = res.data.data;
if(this.autoSelect===true&&this.xmProjects.length>0){
var row=this.xmProjects[0];
this.$refs.table.setCurrentRow(row);
this.rowClick(row);
}
}else{
this.$notify({showClose: true, message: tips.msg, type: 'error' });
}
this.load.list = false;
}).catch( err => this.load.list = false );
},
selectProject:function(row){
this.editForm=row
this.$emit('project-confirm',this.editForm);
}
/**end 自定义函数请在上面加**/
,
clearSelect(){
this.$refs.table.setCurrentRow();
this.$emit("clear-select");
},
close(){
this.$emit("close");
}
},//end methods
components: {
//
},
mounted() {
this.$nextTick(() => {
this.maxTableHeight = util.calcTableMaxHeight(this.$refs.table.$el);
this.showInfo = false;
this.getXmProjects();
});
}
}
</script>
<style scoped>
.align-right{
float: right;
}
</style>

22
src/views/xm/core/xmProjectState/XmProjectStateMng.vue

@ -1,12 +1,14 @@
<template>
<section class="page-container padding border">
<el-row>
<el-input style="width:20%;" v-model="filters.selProject.name" @click.native="onProjectInputClick" clearable @clear="closeSelectProject" placeholder="点击选择项目"></el-input>
<el-input v-model="filters.key" style="width: 20%;" placeholder="项目名称模糊查询"> </el-input>
<el-button v-loading="load.list" :disabled="load.list==true" v-on:click="searchXmProjectStates" icon="el-icon-search"></el-button>
<el-button type="success" @click="loadTasksToXmProjectState" icon="el-icon-s-data">刷新数据</el-button>
<el-button type="success" @click="loadTasksSettleToXmProjectState" icon="el-icon-s-data">刷新结算数据</el-button>
<xm-project-select :auto-select="false" @row-click="onPorjectConfirm(loadTasksToXmProjectState,$event)">
<font slot="title">刷新任务统计数据</font>
</xm-project-select>
<xm-project-select :auto-select="false" @row-click="onPorjectConfirm(loadTasksSettleToXmProjectState,$event)">
<font slot="title">刷新结算数据</font>
</xm-project-select>
</el-row>
<el-row class="page-main">
<!--列表 XmProjectState 项目指标日统计表-->
@ -105,9 +107,6 @@
<el-drawer title="新增项目指标日统计表" :visible.sync="addFormVisible" size="50%" append-to-body :close-on-click-modal="false">
<xm-project-state-add :xm-project-state="addForm" :visible="addFormVisible" @cancel="addFormVisible=false" @submit="afterAddSubmit"></xm-project-state-add>
</el-drawer>
<el-drawer title="选中项目" :visible.sync="selectProjectVisible" size="80%" append-to-body :close-on-click-modal="false" @close="nextCommand=null">
<xm-project-list @project-confirm="onPorjectConfirm"></xm-project-list>
</el-drawer>
</el-row>
</section>
</template>
@ -120,7 +119,7 @@
import XmProjectStateAdd from './XmProjectStateAdd';//
import XmProjectStateEdit from './XmProjectStateEdit';//
import { mapGetters } from 'vuex'
import XmProjectList from '../xmProject/XmProjectList';
import XmProjectSelect from '@/views/xm/core/components/XmProjectSelect.vue';
export default {
computed: {
@ -376,10 +375,9 @@
},
/**begin 自定义函数请在下面加**/
onPorjectConfirm:function(project){
onPorjectConfirm:function(nextCommand,project){
this.filters.selProject={...project}
this.selectProjectVisible=false;
if(this.nextCommand){
if(nextCommand){
this.nextCommand();
}else{
this.searchXmProjectStates();
@ -429,7 +427,7 @@
},//end methods
components: {
'xm-project-state-add':XmProjectStateAdd,
'xm-project-state-edit':XmProjectStateEdit, XmProjectList
'xm-project-state-edit':XmProjectStateEdit,XmProjectSelect,
//
},
mounted() {

23
src/views/xm/core/xmQuestion/XmQuestionAdd.vue

@ -12,16 +12,16 @@
<el-form :model="addForm" label-width="120px" :rules="addFormRules" ref="addForm">
<el-form-item label="缺陷标题" prop="name">
<el-input v-model="addForm.name" placeholder="缺陷标题" ></el-input>
<br><el-tooltip content="隶属需求">
<el-tag closable @click="showSelectMenu" @close.stop="handleCloseMenuTag">
<el-tag title="隶属需求" closable @click="showSelectMenu" @close.stop="handleCloseMenuTag">
<div class="icon" :style="{backgroundColor: 'rgb(79, 140, 255)' }">
<i :class=" 'el-icon-document' " ></i>
</div> {{addForm.menuName?addForm.menuName:"未关联需求"}}</el-tag></el-tooltip>
</div> {{addForm.menuName?addForm.menuName:"未关联需求"}}</el-tag>
</el-form-item>
<el-row>
<el-col :span="12">
<el-form-item label="归属项目" prop="projectId">
<el-tag :closable="!selProject" @click="showProjectList" @close.stop="clearProject">{{this.filters.selProject?this.filters.selProject.name:'未关联项目'}}</el-tag>
<font v-if="filters.selProject">{{this.filters.selProject?this.filters.selProject.name:''}}</font>
<xm-project-select ref="xmProjectSelect" v-if="!selProject" @row-click="onPorjectConfirm"></xm-project-select>
</el-form-item>
</el-col>
<el-col :span="12">
@ -130,11 +130,7 @@
</el-drawer>
<el-drawer append-to-body title="需求选择" :visible.sync="selectMenuVisible" size="70%" :close-on-click-modal="false">
<xm-menu-select :is-select-menu="true" @selected="onSelectedMenu" :sel-project="filters.selProject"></xm-menu-select>
</el-drawer>
<el-drawer title="选中项目" :visible.sync="selectProjectVisible" size="70%" append-to-body :close-on-click-modal="false">
<xm-project-list @project-confirm="onPorjectConfirm"></xm-project-list>
<xm-menu-select :is-select-menu="true" checkScope="0" @selected="onSelectedMenu" :sel-project="filters.selProject"></xm-menu-select>
</el-drawer>
</el-row>
<el-row>
@ -155,7 +151,7 @@
import XmGroupMng from '../xmGroup/XmGroupSelect';
import xmMenuSelect from '../xmMenu/XmMenuSelect';
import XmProjectList from '../xmProject/XmProjectList';
import XmProjectSelect from '@/views/xm/core/components/XmProjectSelect';
import XmTaskList from '../xmTask/XmTaskList';
@ -236,6 +232,7 @@
opStepEditorVisible:false,
expectResultEditorVisible:false,
descriptionEditorVisible:false,
xmProductVersions:[{id:"1.0.0" ,name:'1.0.0'}],
/**end 在上面加自定义属性**/
}//end return
@ -375,6 +372,7 @@
showSelectMenu:function(){
if(this.filters.selProject==null){
this.$notify({showClose: true, message: "请先选项目", type: 'error' });
this.$refs.xmProjectSelect.projectVisible=true;
return ;
}
this.selectMenuVisible=true;
@ -399,9 +397,6 @@
this.addForm.handlerUsername=this.addForm.askUsername
this.addForm.handlerUserid=this.addForm.askUserid
},
showProjectList:function(){
this.selectProjectVisible=true;
},
onPorjectConfirm:function(project){
this.filters.selProject=project
this.addForm.projectId=project.id
@ -433,7 +428,7 @@
},//end method
components: {
// 'xm-question-edit':XmQuestionEdit
'upload': AttachmentUpload,XmGroupMng,VueEditor,XmTaskList,xmMenuSelect,XmProjectList
'upload': AttachmentUpload,XmGroupMng,VueEditor,XmTaskList,xmMenuSelect,XmProjectSelect
},
mounted() {
console.log("question_add");

53
src/views/xm/core/xmQuestion/XmQuestionEdit.vue

@ -2,11 +2,19 @@
<section class="page-container padding border">
<el-row class="padding-bottom">
<el-steps :active="calcBugStep" simple finish-status="success">
<el-step title="已激活,待确认" description="创建后自动激活、关闭后重新激活)"></el-step>
<el-step title="已确认,待解决" description="业务确认缺陷后变为已确认"></el-step>
<el-step title="已解决,待关闭" description="开发修复缺陷后,变成已解决"></el-step>
<el-step title="已关闭(可重新激活)" description="测试通过后变为已关闭,已关闭缺陷可以重新激活"></el-step>
<!--1|新提交
2|处理中
3|已修复
4|重新打开
5|已发布
6|已拒绝
7|挂起 -->
<el-steps :active="calcBugStep" simple finish-status="success" >
<el-step v-for="(item,index) in dicts['bugStatus']" :title="item.name" :key="index" @click.native.stop="editForm.bugStatus=item.id">
<el-link slot="title" @click="editForm.bugStatus=item.id">
{{item.name}}
</el-link>
</el-step>
</el-steps>
</el-row>
<el-row class="page-main ">
@ -137,22 +145,13 @@
</el-drawer>
<el-drawer append-to-body title="需求选择" :visible.sync="selectMenuVisible" size="70%" :close-on-click-modal="false">
<xm-menu-select :is-select-menu="true" @selected="onSelectedMenu" :sel-project="selProject"></xm-menu-select>
<xm-menu-select :is-select-menu="true" checkScope="0" @selected="onSelectedMenu" :sel-project="selProject"></xm-menu-select>
</el-drawer>
</el-row>
</el-row>
<el-row class="page-bottom">
<el-button @click.native="handleCancel">取消</el-button>
<el-button v-if="editForm.bugStatus !='closed'" v-loading="load.edit" type="primary" @click.native="handleQuestion(editForm.bugStatus)" :disabled="load.edit==true">保存</el-button>
<el-button v-if="editForm.bugStatus=='active'" v-loading="load.edit" type="primary" @click.native="handleQuestion('confirmed')" :disabled="load.edit==true">确认</el-button>
<el-button v-if="editForm.bugStatus=='active'" v-loading="load.edit" type="primary" @click.native="handleQuestion('active')" :disabled="load.edit==true">不是缺陷</el-button>
<el-button v-if="editForm.bugStatus=='active'" v-loading="load.edit" type="primary" @click.native="handleQuestion('resolved')" :disabled="load.edit==true">直接解决</el-button>
<el-button v-if="editForm.bugStatus=='active'" v-loading="load.edit" type="primary" @click.native="handleQuestion('closed')" :disabled="load.edit==true">直接关闭</el-button>
<el-button v-if="editForm.bugStatus=='confirmed'" v-loading="load.edit" type="primary" @click.native="handleQuestion('resolved')" :disabled="load.edit==true">解决</el-button>
<el-button v-if="editForm.bugStatus=='confirmed'" v-loading="load.edit" type="primary" @click.native="handleQuestion('closed')" :disabled="load.edit==true">关闭</el-button>
<el-button v-if="editForm.bugStatus=='resolved'" v-loading="load.edit" type="primary" @click.native="handleQuestion('closed')" :disabled="load.edit==true">关闭</el-button>
<el-button v-if="editForm.bugStatus=='resolved'" v-loading="load.edit" type="primary" @click.native="handleQuestion('active')" :disabled="load.edit==true">重新激活</el-button>
<el-button v-if="editForm.bugStatus=='closed'" v-loading="load.edit" type="primary" @click.native="handleQuestion('active')" :disabled="load.edit==true">重新激活</el-button>
<el-button v-loading="load.edit" type="primary" @click.native="handleQuestion(editForm.bugStatus)" :disabled="load.edit==true">保存</el-button>
</el-row>
@ -190,17 +189,19 @@
]),
calcBugStep(){
if(this.editForm.bugStatus=='active'){
return 1
}else if(this.editForm.bugStatus=='confirmed'){
return 2
}else if(this.editForm.bugStatus=='resolved'){
return 3
}else if(this.editForm.bugStatus=='closed'){
return 4
if(this.dicts['bugStatus'] && this.editForm){
var index=this.dicts['bugStatus'].findIndex(i=>{
if(i.id==this.editForm.bugStatus){
return true;
}else{
return false;
}
})
return index+1;
}else{
return 1;
return 0;
}
}
},
props:['xmQuestion','visible',"selProject"],
@ -241,7 +242,7 @@
},
// xm_question
editForm: {
id:'',name:'',projectId:'',projectName:'',taskId:'',taskName:'',endTime:'',askUserid:'',askUsername:'',handlerUserid:'',handlerUsername:'',priority:'',solution:'',processTime:'',receiptMessage:'',receiptTime:'',description:'',createUserid:'',createUsername:'',createTime:'',status:'',receiptMessage:'',
id:'',name:'',projectId:'',projectName:'',taskId:'',taskName:'',endTime:'',askUserid:'',askUsername:'',handlerUserid:'',handlerUsername:'',priority:'',solution:'',processTime:'',receiptMessage:'',receiptTime:'',description:'',createUserid:'',createUsername:'',createTime:'',bugStatus:'',receiptMessage:'',
attachment: [],iterationId:'',iterationName:'',productId:'',
},
/**begin 在下面加自定义属性,记得补上面的一个逗号**/

330
src/views/xm/core/xmQuestion/XmQuestionMng.vue

@ -1,7 +1,10 @@
<template>
<section class="padding">
<el-row>
<el-select v-model="filters.bugStatus" placeholder="状态" style="width:100px;" clearable @change="changeBugStatus">
<xm-product-select v-if="!xmProduct" style="display:inline;" :auto-select="false" :link-project-id="selProject?selProject.id:null" @row-click="onProductSelected" @clear-select="clearProduct"></xm-product-select>
<xm-project-select v-if="!selProject" style="display:inline;" ref="xmProjectSelect" :auto-select="false" :link-product-id="xmProduct?xmProduct.id:null" @row-click="onProjectConfirm" @clear-select="clearProject"></xm-project-select>
<el-select v-model="filters.bugStatus" placeholder="状态" style="width:100px;" clearable @change="changeBugStatus">
<el-option v-for="(b,index) in dicts['bugStatus']" :value="b.id" :key="index" :label="b.name">{{b.name}}
</el-option>
</el-select>
@ -14,8 +17,8 @@
</el-option>
</el-select>
<el-button v-if="!filters.tags||filters.tags.length==0" @click.native="tagSelectVisible=true">标签</el-button>
<el-tag v-else @click="tagSelectVisible=true" closable @close="clearFiltersTag(filters.tags[0])">{{filters.tags[0].tagName.substr(0,5)}}({{filters.tags.length}})</el-tag>
<el-button v-if="!filters.tags||filters.tags.length==0" @click.native="$refs.tagDialog.open()">标签</el-button>
<el-tag v-else @click="$refs.tagDialog.open()" closable @close="clearFiltersTag(filters.tags[0])">{{filters.tags[0].tagName.substr(0,5)}}({{filters.tags.length}})</el-tag>
<el-input style="width:200px;" v-model="filters.key" placeholder="缺陷名称" clearable>
</el-input>
@ -26,15 +29,6 @@
width="600"
trigger="click" >
<el-row>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">产品:</font><el-tag v-if=" filters.product " closable @close="clearProduct">{{this.filters.product.productName}}</el-tag>
<el-button v-else @click="showProductVisible" type="plian">选产品</el-button>
</el-col>
<el-col :span="24" style="padding-top:12px;" v-if="!selProject">
<font class="more-label-font">项目:</font>
<el-tag v-if="filters.selProject && !selProject" closable @close="clearProject" @click="showProjectList(true)">{{ filters.selProject.name }}</el-tag>
<el-button v-else @click="showProjectList(true)" >选择项目</el-button>
</el-col>
<el-col :span="24" style="padding-top:12px;">
<font class="more-label-font">需求:</font>
<el-button v-if=" !filters.menus || filters.menus.length==0" @click="showMenu"> 需求</el-button>
@ -120,8 +114,7 @@
<el-button slot="reference" icon="el-icon-more"></el-button>
</el-popover>
<span style="float:right;">
<el-button type="primary" icon="el-icon-plus" @click="showAdd" round>
</el-button>
<el-button type="primary" icon="el-icon-plus" @click="showAdd" round> </el-button>
</span>
</el-row>
<el-row class="padding-top">
@ -132,27 +125,56 @@
<el-table-column prop="name" label="缺陷名称" min-width="150">
<template slot-scope="scope">
<span class="vlink" @click="showEdit(scope.row)" :title="scope.row.name">
<el-tag type="info" v-if="scope.row.bugSeverity=='4' ">{{formatterOption(scope.row,{property:'bugSeverity'},scope.row.bugSeverity)}}</el-tag>
<el-tag type="primary" v-else-if="scope.row.bugSeverity=='3'">{{formatterOption(scope.row,{property:'bugSeverity'},scope.row.bugSeverity)}}</el-tag>
<el-tag type="warning" v-else-if="scope.row.bugSeverity=='2'">{{formatterOption(scope.row,{property:'bugSeverity'},scope.row.bugSeverity)}}</el-tag>
<el-tag type="danger" v-else-if="scope.row.bugSeverity=='1'">{{formatterOption(scope.row,{property:'bugSeverity'},scope.row.bugSeverity)}}</el-tag>
<el-tag v-else>{{formatterOption(scope.row,{property:'bugSeverity'},scope.row.bugSeverity)}}</el-tag>
&nbsp;&nbsp;{{scope.row.name}}
{{scope.row.name}}
</span>
</template>
</el-table-column>
<el-table-column prop="bugStatus" label="状态" width="100">
<template slot-scope="scope">
<el-tag type="info" v-if="scope.row.bugStatus=='create' ">创建</el-tag>
<el-tag type="primary" v-else-if="scope.row.bugStatus=='active'">已激活</el-tag>
<el-tag type="warning" v-else-if="scope.row.bugStatus=='confirm'">确认</el-tag>
<el-tag type="warning" v-else-if="scope.row.bugStatus=='confirmed'">已确认</el-tag>
<el-tag type="success" v-else-if="scope.row.bugStatus=='solve'">解决</el-tag>
<el-tag type="success" v-else-if="scope.row.bugStatus=='resolved'">已解决</el-tag>
<el-tag type="success" v-else-if="scope.row.bugStatus=='close'">关闭</el-tag>
<el-tag type="success" v-else-if="scope.row.bugStatus=='closed'">已关闭</el-tag>
<el-tag v-else>{{scope.row.bugStatus}}</el-tag>
<div class="cell-text">
<el-button style="display:block;" :type="item.className" plain round v-for="(item,index) in [formatterBugStatusDicts(scope.row.bugStatus)]" :key="index">{{item.name}}</el-button>
</div>
<span class="cell-bar">
<el-select v-model="scope.row.bugStatus" placeholder="类型" style="display:block;" @change="editXmQuestionSomeFields(scope.row,'bugStatus',$event)">
<el-option :value="item.id" :label="item.name" v-for="(item,index) in dicts.bugStatus" :key="index"></el-option>
</el-select>
</span>
</template>
</el-table-column>
<el-table-column prop="priority" label="优先级" width="100">
<template slot-scope="scope">
<div class="cell-text">
<el-button style="display:block;" :type="item.className" plain round v-for="(item,index) in [formatterPriorityDicts(scope.row.priority)]" :key="index">{{item.name}}</el-button>
</div>
<span class="cell-bar">
<el-select v-model="scope.row.priority" placeholder="优先级" style="display:block;" @change="editXmQuestionSomeFields(scope.row,'priority',$event)">
<el-option :value="item.id" :label="item.name" v-for="(item,index) in dicts.priority" :key="index"></el-option>
</el-select>
</span>
</template>
</el-table-column>
<el-table-column prop="solution" label="解决方案" width="100">
<template slot-scope="scope">
<div class="cell-text">
{{formaterByDicts(scope.row,'solution',scope.row.solution)}}
</div>
<span class="cell-bar">
<el-select v-model="scope.row.solution" placeholder="类型" style="display:block;" @change="editXmQuestionSomeFields(scope.row,'solution',$event)">
<el-option :value="item.id" :label="item.name" v-for="(item,index) in dicts.bugSolution" :key="index"></el-option>
</el-select>
</span>
</template>
</el-table-column>
<el-table-column prop="bugSeverity" label="严重程度" width="100">
<template slot-scope="scope">
<div class="cell-text">
{{formaterByDicts(scope.row,'bugSeverity',scope.row.bugSeverity)}}
</div>
<span class="cell-bar">
<el-select v-model="scope.row.bugSeverity" placeholder="类型" style="display:block;" @change="editXmQuestionSomeFields(scope.row,'bugSeverity',$event)">
<el-option :value="item.id" :label="item.name" v-for="(item,index) in dicts.bugSeverity" :key="index"></el-option>
</el-select>
</span>
</template>
</el-table-column>
<el-table-column prop="askUsername" label="创建人" width="100" show-overflow-tooltip>
@ -163,16 +185,27 @@
<el-table-column prop="ltime" label="更新时间" sortable width="100" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="handlerUsername" label="指派给" width="100" show-overflow-tooltip>
<el-table-column prop="handlerUsername" label="负责人" width="100" show-overflow-tooltip>
<template slot-scope="scope">
<div class="cell-text">
{{ scope.row.handlerUsername}}
</div>
<span class="cell-bar">
<el-button @click="showGroupUsers('editHandlerUserid',scope.row)">负责人</el-button>
</span>
</template>
</el-table-column>
<el-table-column prop="tagNames" label="标签" width="100" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="menuName" label="需求" width="100" show-overflow-tooltip></el-table-column>
<el-table-column header-align="center" label="操作" fixed="right" width="100">
<template slot-scope="scope">
<el-button type="primary" @click.stop="showEdit(scope.row)" >编辑</el-button>
<div class="cell-text">
{{ scope.row.tagNames}}
</div>
<span class="cell-bar">
<el-button @click="$refs.tagDialog.open({data:scope.row,action:'editTagIds'})">标签</el-button>
</span>
</template>
</el-table-column>
<el-table-column prop="menuName" label="需求" width="100" show-overflow-tooltip></el-table-column>
</el-table>
<el-pagination layout="total, sizes, prev, pager, 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>
@ -185,26 +218,13 @@
<el-drawer title="新增缺陷" :visible.sync="addFormVisible" :with-header="false" size="70%" append-to-body :close-on-click-modal="false">
<xm-question-add :xm-test-case-exec="xmTestCaseExec" :xm-test-case="xmTestCase" :qtype="qtype" :sel-project=" filters.selProject " :xm-question="addForm" :visible="addFormVisible" @cancel="addFormVisible=false" @submit="afterAddSubmit"></xm-question-add>
</el-drawer>
<el-drawer title="选中用户" v-if=" filters.selProject " :visible.sync="selectUserVisible" size="70%" append-to-body :close-on-click-modal="false">
<xm-group-mng :sel-project=" filters.selProject " :is-select-single-user="1" @user-confirm="onUserConfirm"></xm-group-mng>
</el-drawer>
<el-drawer title="选中项目" :visible.sync="selectProjectVisible" size="70%" append-to-body :close-on-click-modal="false">
<xm-project-list @project-confirm="onPorjectConfirm"></xm-project-list>
</el-drawer>
<xm-group-dialog ref="xmGroupDialog" :sel-project=" filters.selProject " :is-select-single-user="1" @user-confirm="onUserConfirm"></xm-group-dialog>
<el-drawer append-to-body title="需求选择" :visible.sync="menuVisible" size="70%" :close-on-click-modal="false">
<xm-menu-select :visible="menuVisible" :is-select-menu="true" :multi="true" @menus-selected="onSelectedMenus" ></xm-menu-select>
</el-drawer>
<el-drawer title="选择产品" :visible.sync="productSelectVisible" size="70%" append-to-body :close-on-click-modal="false">
<xm-product-select :isSelectProduct="true" :selProject="filters.selProject" :visible="productSelectVisible" @cancel="productSelectVisible=false" @selected="onProductSelected"></xm-product-select>
</el-drawer>
<el-drawer append-to-body title="标签条件" :visible.sync="tagSelectVisible" :close-on-click-modal="false" size="60%">
<tag-mng :tagIds="filters.tags?filters.tags.map(i=>i.tagId):[]" :jump="true" @select-confirm="onTagSelected">
</tag-mng>
</el-drawer>
</section>
<tag-dialog ref="tagDialog" :tagIds="filters.tags?filters.tags.map(i=>i.tagId):[]" :jump="true" @select-confirm="onTagSelected"></tag-dialog>
</section>
</template>
<script>
@ -213,17 +233,17 @@
import config from '@/common/config';//
//import Sticky from '@/components/Sticky' // header
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { listXmQuestion, delXmQuestion, batchDelXmQuestion, editStatus } from '@/api/xm/core/xmQuestion';
import { listXmQuestion, delXmQuestion, batchDelXmQuestion, editStatus ,editXmQuestionSomeFields} from '@/api/xm/core/xmQuestion';
import XmQuestionAdd from './XmQuestionAdd';//
import XmQuestionEdit from './XmQuestionEdit';//
import { mapGetters } from 'vuex'
import xmMenuSelect from '../xmMenu/XmMenuSelect';
import XmGroupMng from '../xmGroup/XmGroupMng';
import XmProjectList from '../xmProject/XmProjectList';
import XmGroupDialog from '../xmGroup/XmGroupDialog';
import XmProjectSelect from '@/views/xm/core/components/XmProjectSelect';
import XmProductSelect from '../xmProduct/XmProductSelect';//
import TagMng from "@/views/mdp/arc/tag/TagMng";
import XmProductSelect from '@/views/xm/core/components/XmProductSelect';//
import TagDialog from '@/views/mdp/arc/tag/TagDialog.vue';
export default {
computed: {
@ -533,11 +553,10 @@
},
// XmQuestion xm_question
showAdd: function () {
if(this.filters.selProject==null){
if(!this.filters.selProject){
this.$notify({showClose: true, message: "请先选中项目", type: 'warning' });
this.$refs.xmProjectSelect.projectVisible=true;
this.nextAction="showAdd"
this.showProjectList();
return;
}
this.addFormVisible = true;
@ -663,27 +682,68 @@
}
},
showSolveName:function(row){
if(row.bugStatus=='active'){
return "去确认"
}else if(row.bugStatus=='confirmed'){
return "去解决"
}else if(row.bugStatus=='resolved'){
return "去关闭"
}else if(row.bugStatus=='closed'){
return "激活"
formatterPriorityDicts(cellValue){
var key="priority";
if(this.dicts[key]==undefined || this.dicts[key]==null || this.dicts[key].length==0 ){
return {id:cellValue,name:cellValue,className:'primary'};
}
var list=this.dicts[key].filter(i=>i.id==cellValue)
if(list.length>0){
var data= {...list[0],className:'primary'}
if(data.id=='0'){
data.className='danger'
}else if(data.id=='1'){
data.className='warning'
}else if(data.id=='2'){
data.className='success'
}else if(data.id=='3'){
data.className='primary'
}else if(data.id=='4'){
data.className='info'
}else{
data.className='primary'
}
return data;
}else{
return {id:cellValue,name:cellValue,className:'primary'}
}
},
showGroupUsers:function(userType){
this.userType=userType;
if(this.filters.selProject==null || this.filters.selProject.id==''){
this.$notify({showClose: true, message: "请先选中项目", type: 'warning' });
this.nextAction="showGroupUsers"
this.showProjectList();
return;
formatterBugStatusDicts: function(cellValue){
var key="bugStatus";
if(this.dicts[key]==undefined || this.dicts[key]==null || this.dicts[key].length==0 ){
return {id:cellValue,name:cellValue,className:'primary'};
}
var list=this.dicts[key].filter(i=>i.id==cellValue)
if(list.length>0){
var data= {...list[0],className:'primary'}
if(data.id=='1'){
data.className='primary'
}else if(data.id=='2'){
data.className='primary'
}else if(data.id=='3'){
data.className='success'
}else if(data.id=='4'){
data.className='warning'
}else if(data.id=='5'){
data.className='success'
}else if(data.id=='6'){
data.className='info'
}else if(data.id=='7'){
data.className='info'
}else{
data.className='danger'
}
return data;
}else{
return {id:cellValue,name:cellValue,className:'primary'}
}
this.selectUserVisible=true;
},
showGroupUsers:function(userType,row){
this.$refs.xmGroupDialog.open({data:row,action:userType})
},
handleExport() {
this.downloadLoading = true
let header = [];
@ -739,21 +799,24 @@
},
/**end 自定义函数请在上面加**/
onUserConfirm:function(groupUsers){
if(this.userType=='createUser'){
onUserConfirm:function(groupUsers,option){
if(option.action=='createUser'){
if(groupUsers==null || groupUsers.length==0){
this.filters.createUser=null
}else{
var user=groupUsers[0]
this.filters.createUser=user
}
}else if(this.userType=='hisHandler'){
}else if(option.action=='hisHandler'){
if(groupUsers==null || groupUsers.length==0){
this.filters.hisHandler=null
}else{
var user=groupUsers[0]
this.filters.hisHandler=user
}
}else if(option.action=='editHandlerUserid'){
this.editXmQuestionSomeFields(option.data,"handlerUserid",groupUsers)
return;
}else{
if(groupUsers==null || groupUsers.length==0){
this.filters.handlerUserid=''
@ -769,19 +832,13 @@
this.searchXmQuestions();
},
showProjectList:function(clear){
if(clear){
this.nextAction="";
}
this.selectProjectVisible=true;
},
onPorjectConfirm:function(project){
onProjectConfirm:function(project){
this.filters.selProject=project
this.selectProjectVisible=false;
if(this.nextAction=='showAdd'){
if( this.nextAction=='showAdd'){
this.showAdd()
}else if(this.nextAction=='showGroupUsers'){
}else if( this.nextAction=='showGroupUsers'){
this.showGroupUsers(this.userType)
}else{
this.searchXmQuestions();
@ -920,21 +977,94 @@
return msg;
},
onTagSelected(tags) {
this.tagSelectVisible = false;
if (!tags || tags.length == 0) {
this.filters.tags=[]
onTagSelected(tags,option) {
if(option.action=="editTagIds"){
this.editXmQuestionSomeFields(option.data,"tagIds",tags);
}else{
this.filters.tags=tags
if (!tags || tags.length == 0) {
this.filters.tags=[]
}else{
this.filters.tags=tags
}
this.searchXmQuestions();
}
this.searchXmQuestions();
}
},
editXmQuestionSomeFields(row,fieldName,$event){
var params={ids:[row.id]};
if(this.sels.length>0){
if(!this.sels.some(k=>k.id==row.id)){
this.$notify({showClose:true,message:'请操作选中的行或者取消选中的行再操作其它行',type:'warning'})
return;
}
params.ids=this.sels.map(i=>i.id)
}
if(fieldName==='handlerUserid'){
if($event){
params[fieldName]=$event[0].userid;
params.handlerUsername=$event[0].username
}else{
return;
}
}else if(fieldName==='tagIds'){
if($event){
params[fieldName]=$event.map(i=>i.tagId).join(",");
params.tagNames=$event.map(i=>i.tagName).join(",");
}else{
return;
}
}else if(fieldName==='workload'){
params={...params,...$event}
}else{
params[fieldName]=$event
}
editXmQuestionSomeFields(params).then(res=>{
var tips = res.data.tips;
if(tips.isOk){
if(this.sels.length>0){
this.sels.forEach(i=>{
Object.assign(i,params)
})
}else{
Object.assign(row,params)
}
}else{
this.$notify({showClose:true,message:tips.msg,type:tips.isOk?'success':'error'})
}
})
},
/**
* 'bugSeverity','bugSolution','bugStatus','bugType','priority'bugRepRate
*/
formaterByDicts(row,property,cellValue){
var property=property
var dict=null;
if(property=='bugSeverity'){
dict=this.dicts['bugSeverity']
}else if(property=='solution'){
dict=this.dicts['bugSolution']
}else if(property=='bugStatus'){
dict=this.dicts['bugStatus']
}else if(property=='priority'){
dict=this.dicts['priority']
}else if(property=='bugType'){
dict=this.dicts['bugType']
}else if(property=='repRate'){
dict=this.dicts['bugRepRate']
}
if(!dict){
return cellValue;
}else{
var item=dict.find(i=>i.id==cellValue)
return item?item.name:cellValue;
}
},
},//end methods
components: {
'xm-question-add':XmQuestionAdd,
'xm-question-edit':XmQuestionEdit,
XmGroupMng,XmProjectList,xmMenuSelect,XmProductSelect,TagMng,
XmGroupDialog,XmProjectSelect,xmMenuSelect,XmProductSelect, TagDialog
//
},
mounted() {
@ -955,13 +1085,9 @@
this.maxTableHeight = util.calcTableMaxHeight(this.$refs.table.$el);
this.getXmQuestions();
});
initSimpleDicts('all',['bugSeverity','bugSolution','bugStatus','bugType','priority']).then(res=>{
initSimpleDicts('all',['bugSeverity','bugSolution','bugStatus','bugType','priority','bugRepRate']).then(res=>{
if(res.data.tips.isOk){
this.dicts['bugSeverity']=res.data.data.bugSeverity
this.dicts['bugSolution']=res.data.data.bugSolution
this.dicts['bugStatus']=res.data.data.bugStatus
this.dicts['bugType']=res.data.data.bugType
this.dicts['priority']=res.data.data.priority
this.dicts=res.data.data;
}
});
}

2
src/views/xm/core/xmTask/XmTaskAgileKanban.vue

@ -134,7 +134,7 @@ export default {
methods: {
onMove(e) {
console.log('onMove--e==', e);
debugger;
let targetEl = { ...e.dragged.dataset };
let toEl = { ...e.to.dataset };
if (targetEl.menuId === toEl.menuId && targetEl.taskState != toEl.taskState) {

4
src/views/xm/core/xmTask/XmTaskList.vue

@ -99,7 +99,7 @@
import { initSimpleDicts } from '@/api/mdp/meta/item';//
import { getTask ,listXmTask,editXmTask,editRate, delXmTask, batchDelXmTask,batchImportTaskFromTemplate,batchSaveBudget } from '@/api/xm/core/xmTask';
import { mapGetters } from 'vuex';
import XmProjectSelect from '../xmProject/XmProjectSelect';
import XmProjectSelect from '@/views/xm/core/components/XmProjectSelect';
export default {
computed: {
@ -521,7 +521,7 @@
},
mounted() {
this.filters.selProject=this.selProject
debugger;
this.$nextTick(()=>{
this.tableHeight = util.calcTableMaxHeight(this.$refs.taskTable.$el);
this.getXmTasks();

6
src/views/xm/core/xmTask/XmTaskMng.vue

@ -1122,10 +1122,10 @@ import xmMenuSelect from "../xmMenu/XmMenuSelect";
import { addXmMyFocus, delXmMyFocus } from "@/api/xm/core/xmMyFocus";
import XmProjectSelect from "../xmProject/XmProjectSelect";
import XmProjectSelect from "@/views/xm/core/components/XmProjectSelect";
import XmMenuRichDetail from "../xmMenu/XmMenuRichDetail";
import XmProductSelect from "../xmProduct/XmProductSelect"; //
import XmProductSelect from "@/views/xm/core/components/XmProductSelect"; //
import TagMng from "@/views/mdp/arc/tag/TagMng";
import XmGantt from "../components/xm-gantt";
@ -2521,7 +2521,7 @@ export default {
var tips = res.data.tips;
if(tips.isOk){
this.searchXmTasks();
debugger;
var rows=[...this.sels,{id:'xxxxx',parentTaskid:task.id}]
treeTool.reloadAllChildren(this.$refs.table,this.maps,rows,'parentTaskid',this.loadXmTaskLazy)
}

135
src/views/xm/core/xmTaskSbill/SelectXmProject.vue

@ -0,0 +1,135 @@
<template>
<section class="page-container padding">
<el-row class="page-header">
<el-input v-model="filters.key" style="width:50%;" placeholder="项目名称模糊查询" clearable>
</el-input>
<el-button type="primary" icon="el-icon-search" @click="searchXmProjects">查询</el-button>
</el-row>
<el-row>
<el-row>
<el-table ref="table" v-cloak fit border :data="xmProjects" highlight-current-row v-loading="load.list"
style="width: 100%;" :header-cell-style="{'text-align':'center'}"
:cell-style="{'text-align':'center'}">
<el-table-column type="index" label="序号" min-width="50" ></el-table-column>
<el-table-column prop="id" label="项目编码" min-width="100" show-overflow-tooltip></el-table-column>
<el-table-column prop="name" label="标题" min-width="150" ></el-table-column>
<el-table-column label="操作" min-width="80">
<template slot-scope="scope">
<el-button @click.stop="selectRow(scope.row)" >选择</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination layout="total, sizes, prev, pager, 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>
</el-row>
</section>
</template>
<script>
import util from '@/common/js/util';//
import { getDicts,initSimpleDicts,initComplexDicts } from '@/api/mdp/meta/item';//
import { addXmTaskSbill,editXmTaskSbill } from '@/api/xm/core/xmTaskSbill';
import { mapGetters } from 'vuex'
import {listXmProject} from "@/api/xm/core/xmProject";
export default {
components: {
//XmTaskSbillEdit,
},
computed: {
...mapGetters([ 'userInfo' ]),
},
props:['visible'],
watch: {
'visible':function(visible) {
if(visible==true){
//
this.initData()
}
}
},
data() {
return {
filters: {
key: ''
},
load:{ list: false, edit: false, del: false, add: false },//...
xmProjects:[],
pageInfo:{//
total:0,//0>0
pageSize:10,//
count:false,//
pageNum:1,//1
orderFields:['create_time'],// ['sex','student_id']
orderDirs:['desc']// asc,desc ['asc','desc']
},
}//end return
},//end data
methods: {
//XmTaskSbill @submit="afterEditSubmit"
initData: function(){
this.searchXmProjects();
},
/**begin 在下面加自定义方法**/
handleSizeChange(pageSize) {
this.pageInfo.pageSize=pageSize;
this.getXmProjects();
},
handleCurrentChange(pageNum) {
this.pageInfo.pageNum = pageNum;
this.getXmProjects();
},
// XmProject xm_project
getXmProjects(callBack) {
let params = {
pageSize: this.pageInfo.pageSize,
pageNum: this.pageInfo.pageNum,
total: this.pageInfo.total,
count:this.pageInfo.count,
};
if(this.filters.key!==""){
params.key= "%"+this.filters.key+"%";
}else{
//params.xxx=xxxxx
}
this.load.list = true;
listXmProject(params).then((res) => {
let tips=res.data.tips;
if(tips.isOk){
console.log(res.data);
this.pageInfo.total = res.data.total;
this.pageInfo.count=false;
this.xmProjects = res.data.data;
}else{
this.$message({ showClose: true, message: tips.msg, type: 'error' });
}
this.load.list = false;
}).catch( err => this.load.list = false );
},
selectRow(row){
let obj = {
projectId:row.id,
projectName:row.name
}
this.$emit('select',obj);
},
searchXmProjects(){
this.pageInfo.count=true;
this.getXmProjects();
}
},//end method
mounted() {
this.$nextTick(() => {
//initSimpleDicts('all',['sex','gradeLvl']).then(res=>this.dicts=res.data.data);
this.initData()
});
}
}
</script>
<style scoped>
</style>

217
src/views/xm/core/xmTaskSbill/XmTaskSbillEdit.vue

@ -0,0 +1,217 @@
<template>
<section class="page-container padding">
<el-row class="page-header">
</el-row>
<el-row class="page-main">
<!--编辑界面 XmTaskSbill 任务结算表-->
<el-form :model="editForm" label-width="120px" :rules="editFormRules" ref="editFormRef">
<!-- <el-form-item label="结算单据编号" prop="id">
<el-input v-model="editForm.id" placeholder="结算单据编号"></el-input>
</el-form-item>-->
<el-form-item label="项目ID:" prop="projectId">
<el-button v-if="!editForm.projectId" type="primary" @click="projSelVisible=true" round>选择项目</el-button>
<span v-else>{{editForm.projectId}}</span>
</el-form-item>
<el-form-item label="项目名称:" prop="projectName">
<el-input disabled v-model="editForm.projectName" placeholder="项目名称"></el-input>
</el-form-item>
<el-form-item label="结算单标题:" prop="title">
<el-input v-model="editForm.title" placeholder="结算单标题"></el-input>
</el-form-item>
<!-- <el-form-item label="金额=工时表中结算金额之和" prop="amt">
<el-input v-model="editForm.amt" placeholder="金额=工时表中结算金额之和"></el-input>
</el-form-item>
<el-form-item label="创建时间" prop="ctime">
<el-date-picker type="date" placeholder="选择日期" v-model="editForm.ctime" value-format="yyyy-MM-dd HH:mm:ss" format="yyyy-MM-dd"></el-date-picker>
</el-form-item>
<el-form-item label="创建人编号" prop="cuserid">
<el-input v-model="editForm.cuserid" placeholder="创建人编号"></el-input>
</el-form-item>
<el-form-item label="创建人姓名" prop="cusername">
<el-input v-model="editForm.cusername" placeholder="创建人姓名"></el-input>
</el-form-item>-->
<el-form-item label="备注:" prop="remark">
<el-input v-model="editForm.remark" type="textarea" :autosize="{ minRows: 3}" placeholder="请输入备注"
maxlength="200" show-word-limit></el-input>
</el-form-item>
<el-form-item>
<el-button @click.native="handleCancel">取消</el-button>
<el-button v-loading="load.edit" type="primary" @click.native="saveSubmit" :disabled="load.edit==true">提交</el-button>
</el-form-item>
<!-- <el-form-item label="机构编号" prop="branchId">
<el-input v-model="editForm.branchId" placeholder="机构编号"></el-input>
</el-form-item>
<el-form-item label="部门编号" prop="deptid">
<el-input v-model="editForm.deptid" placeholder="部门编号"></el-input>
</el-form-item>
<el-form-item label="相对方编号(机构写机构号,个人写个人编号)" prop="cpId">
<el-input v-model="editForm.cpId" placeholder="相对方编号(机构写机构号,个人写个人编号)"></el-input>
</el-form-item>
<el-form-item label="相对方名称(机构写机构名称,个人写个人名称)" prop="cpName">
<el-input v-model="editForm.cpName" placeholder="相对方名称(机构写机构名称,个人写个人名称)"></el-input>
</el-form-item>
<el-form-item label="结算工作量=工时表中工时之和" prop="workload">
<el-input v-model="editForm.workload" placeholder="结算工作量=工时表中工时之和"></el-input>
</el-form-item>
<el-form-item label="业务月份yyyy-MM" prop="bizMonth">
<el-input v-model="editForm.bizMonth" placeholder="业务月份yyyy-MM"></el-input>
</el-form-item>
<el-form-item label="业务日期yyyy-MM-dd" prop="bizDate">
<el-input v-model="editForm.bizDate" placeholder="业务日期yyyy-MM-dd"></el-input>
</el-form-item>
<el-form-item label="结算流程状态" prop="bizFlowState">
<el-input v-model="editForm.bizFlowState" placeholder="结算流程状态"></el-input>
</el-form-item>
<el-form-item label="结算流程实例" prop="bizProcInstId">
<el-input v-model="editForm.bizProcInstId" placeholder="结算流程实例"></el-input>
</el-form-item>
<el-form-item label="更新时间" prop="ltime">
<el-date-picker type="date" placeholder="选择日期" v-model="editForm.ltime" value-format="yyyy-MM-dd HH:mm:ss" format="yyyy-MM-dd"></el-date-picker>
</el-form-item>
<el-form-item label="0-待提交,1-已提交,2-已通过,3-已付款,4-已完成" prop="status">
<el-input v-model="editForm.status" placeholder="0-待提交,1-已提交,2-已通过,3-已付款,4-已完成"></el-input>
</el-form-item>
<el-form-item label="最后审核意见" prop="fmsg">
<el-input v-model="editForm.fmsg" placeholder="最后审核意见"></el-input>
</el-form-item>-->
</el-form>
</el-row>
<!--新增 XmTaskSbill 任务结算表界面-->
<el-drawer title="选择项目" :visible.sync="projSelVisible" size="50%" append-to-body :close-on-click-modal="false">
<select-xm-project :visible="projSelVisible" @select="afterProjectSelect"></select-xm-project>
</el-drawer>
</section>
</template>
<script>
import util from '@/common/js/util';//
import { getDicts,initSimpleDicts,initComplexDicts } from '@/api/mdp/meta/item';//
import { addXmTaskSbill,editXmTaskSbill } from '@/api/xm/core/xmTaskSbill';
import { mapGetters } from 'vuex';
import SelectXmProject from "./SelectXmProject";
export default {
components: {
//XmTaskSbillEdit,
SelectXmProject,
},
computed: {
...mapGetters([ 'userInfo' ]),
},
props:['xmTaskSbill','visible','opType'],
watch: {
'xmTaskSbill':function( xmTaskSbill ) {
if(xmTaskSbill){
this.editForm = xmTaskSbill;
}
},
'visible':function(visible) {
if(visible==true){
//
this.initData()
}
}
},
data() {
return {
currOpType:'add',//add/edit
load:{ list: false, edit: false, del: false, add: false },//...
dicts:{},// params={categoryId:'all',itemCodes:['sex']} {sex: [{id:'1',name:''},{id:'2',name:''}]}
editFormRules: {
id: [
//{ required: true, message: '', trigger: 'blur' }
]
},
// XmTaskSbill
editForm: {
id:'',title:'',amt:'',ctime:'',cuserid:'',cusername:'',remark:'',branchId:'',deptid:'',cpId:'',cpName:'',workload:'',bizMonth:'',bizDate:'',bizFlowState:'',bizProcInstId:'',ltime:'',status:'',fmsg:'',projectId:'',projectName:''
},
/**begin 在下面加自定义属性,记得补上面的一个逗号**/
projSelVisible:false,
}//end return
},//end data
methods: {
// @cancel="editFormVisible=false"
handleCancel:function(){
this.$refs['editFormRef'].resetFields();
this.$emit('cancel');
},
//XmTaskSbill @submit="afterEditSubmit"
saveSubmit: function () {
this.$refs.editFormRef.validate((valid) => {
if (valid) {
this.$confirm('确认提交吗?', '提示', {}).then(() => {
this.load.edit=true
let params = Object.assign({}, this.editForm);
let today = new Date();
let year = today.getFullYear();
let m = today.getMonth() + 1;
let d = today.getDay();
params.bizMonth = year+"-"+m;
params.bizDate = year+"-"+m+"-"+d;
if(this.currOpType=='edit'){
editXmTaskSbill(params).then((res) => {
this.load.edit=false
var tips=res.data.tips;
if(tips.isOk){
this.$emit('submit');// @submit="afterEditSubmit"
}
this.$message({ showClose:true, message: tips.msg, type: tips.isOk?'success':'error' });
}).catch( err =>this.load.edit=false);
}else{
addXmTaskSbill(params).then((res) => {
this.load.edit=false
var tips=res.data.tips;
if(tips.isOk){
this.editForm=res.data.data
this.initData()
this.currOpType="edit";
this.$emit('submit');// @submit="afterAddSubmit"
}
this.$message({ showClose:true, message: tips.msg, type: tips.isOk?'success':'error' });
}).catch( err =>this.load.edit=false);
}
});
}
});
},
initData: function(){
this.currOpType=this.opType
if(this.xmTaskSbill){
this.editForm = Object.assign({},this.xmTaskSbill);
}
if(this.opType=='edit'){
}else{
}
},
/**begin 在下面加自定义方法**/
afterProjectSelect(obj){
this.projSelVisible = false;
this.editForm.projectId = obj.projectId;
this.editForm.projectName = obj.projectName;
}
},//end method
mounted() {
this.$nextTick(() => {
//initSimpleDicts('all',['sex','gradeLvl']).then(res=>this.dicts=res.data.data);
this.initData()
});
}
}
</script>
<style scoped>
</style>

265
src/views/xm/core/xmTaskSbill/XmTaskSbillMng.vue

@ -0,0 +1,265 @@
<template>
<section class="page-container border padding">
<el-row>
<el-input v-model="filters.key" style="width: 20%;" placeholder="模糊查询"></el-input>
<el-button v-loading="load.list" :disabled="load.list==true" @click="searchXmTaskSbills" icon="el-icon-search">查询</el-button>
<!-- <el-button type="danger" v-loading="load.del" @click="batchDel" :disabled="this.sels.length===0 || load.del==true" icon="el-icon-delete"></el-button>-->
<span style="float:right;">
<el-button type="primary" icon="el-icon-plus" @click="showAdd" round></el-button>
</span>
</el-row>
<el-row class="padding-top">
<!--列表 XmTaskSbill 任务结算表-->
<el-table ref="xmTaskSbillTable" :data="xmTaskSbills" :height="maxTableHeight" @sort-change="sortChange" highlight-current-row v-loading="load.list" border @selection-change="selsChange" @row-click="rowClick" style="width: 100%;">
<!-- <el-table-column type="selection" width="55" show-overflow-tooltip></el-table-column>-->
<el-table-column label="序号" type="index" min-width="55" show-overflow-tooltip></el-table-column>
<el-table-column prop="id" label="结算单编号" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="title" label="结算单标题" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="amt" label="金额" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="ctime" label="创建时间" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="cuserid" label="创建人编号" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="cusername" label="创建人姓名" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="remark" label="备注" min-width="80" show-overflow-tooltip></el-table-column>
<!-- <el-table-column prop="branchId" label="机构编号" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="deptid" label="部门编号" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="cpId" label="相对方编号(机构写机构号,个人写个人编号)" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="cpName" label="相对方名称(机构写机构名称,个人写个人名称)" min-width="80" show-overflow-tooltip></el-table-column>-->
<el-table-column prop="workload" label="结算工时" min-width="80" show-overflow-tooltip></el-table-column>
<!-- <el-table-column prop="bizMonth" label="业务月份yyyy-MM" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="bizDate" label="业务日期yyyy-MM-dd" min-width="80" show-overflow-tooltip></el-table-column>-->
<el-table-column prop="bizFlowState" label="审批状态" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="bizProcInstId" label="审批编号" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="ltime" label="更新时间" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="status" label="结算单状态" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="fmsg" label="最后审核意见" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="projectId" label="项目编号" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="projectName" label="项目名称" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="120" fixed="right">
<template scope="scope">
<el-button type="text" @click="showEdit( scope.row,scope.$index)" icon="el-icon-edit"></el-button>
<el-button type="text" @click="handleDel(scope.row,scope.$index)" icon="el-icon-delete"></el-button>
</template>
</el-table-column>
</el-table>
<el-pagination layout="total, sizes, prev, pager, 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>
<el-row>
<!--编辑 XmTaskSbill 任务结算表界面-->
<el-drawer title="编辑任务结算单" :visible.sync="editFormVisible" size="60%" append-to-body :close-on-click-modal="false">
<xm-task-sbill-edit op-type="edit" :xm-task-sbill="editForm" :visible="editFormVisible" @cancel="editFormVisible=false" @submit="afterEditSubmit"></xm-task-sbill-edit>
</el-drawer>
<!--新增 XmTaskSbill 任务结算表界面-->
<el-drawer title="新增任务结算单" :visible.sync="addFormVisible" size="60%" append-to-body :close-on-click-modal="false">
<xm-task-sbill-edit op-type="add" :visible="addFormVisible" @cancel="addFormVisible=false" @submit="afterAddSubmit"></xm-task-sbill-edit>
</el-drawer>
</el-row>
</section>
</template>
<script>
import util from '@/common/js/util';//
import config from '@/common/config';//
import { getDicts,initSimpleDicts,initComplexDicts } from '@/api/mdp/meta/item';//
import { listXmTaskSbill, delXmTaskSbill, batchDelXmTaskSbill } from '@/api/xm/core/xmTaskSbill';
import XmTaskSbillEdit from './XmTaskSbillEdit';//
import { mapGetters } from 'vuex'
export default {
components: {
XmTaskSbillEdit,
},
props:['visible'],
computed: {
...mapGetters(['userInfo']),
},
watch:{
visible(val){
if(val==true){
this.initData();
this.searchXmTaskSbills()
}
}
},
data() {
return {
filters: {
key: ''
},
xmTaskSbills: [],//
pageInfo:{//
total:0,//0>0
pageSize:10,//
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:{},// params={categoryId:'all',itemCodes:['sex']} {sex: [{id:'1',name:''},{id:'2',name:''}]}
addFormVisible: false,//xmTaskSbill
//xmTaskSbill
addForm: {
id:'',title:'',amt:'',ctime:'',cuserid:'',cusername:'',remark:'',branchId:'',deptid:'',cpId:'',cpName:'',workload:'',bizMonth:'',bizDate:'',bizFlowState:'',bizProcInstId:'',ltime:'',status:'',fmsg:'',projectId:'',projectName:''
},
editFormVisible: false,//
//xmTaskSbill
editForm: {
id:'',title:'',amt:'',ctime:'',cuserid:'',cusername:'',remark:'',branchId:'',deptid:'',cpId:'',cpName:'',workload:'',bizMonth:'',bizDate:'',bizFlowState:'',bizProcInstId:'',ltime:'',status:'',fmsg:'',projectId:'',projectName:''
},
maxTableHeight:300,
}
},//end data
methods: {
handleSizeChange(pageSize) {
this.pageInfo.pageSize=pageSize;
this.getXmTaskSbills();
},
handleCurrentChange(pageNum) {
this.pageInfo.pageNum = pageNum;
this.getXmTaskSbills();
},
// obj.order=ascending/descending, asc/desc ; obj.prop=,
sortChange( obj ){
if(obj.order==null){
this.pageInfo.orderFields=[];
this.pageInfo.orderDirs=[];
}else{
var dir='asc';
if(obj.order=='ascending'){
dir='asc'
}else{
dir='desc';
}
this.pageInfo.orderFields=[util.toLine(obj.prop)];
this.pageInfo.orderDirs=[dir];
}
this.getXmTaskSbills();
},
searchXmTaskSbills(){
this.pageInfo.count=true;
this.getXmTaskSbills();
},
// XmTaskSbill
getXmTaskSbills() {
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(",")
}
if(this.filters.key){
params.key=this.filters.key
}
this.load.list = true;
listXmTaskSbill(params).then((res) => {
var tips=res.data.tips;
if(tips.isOk){
this.pageInfo.total = res.data.total;
this.pageInfo.count=false;
this.xmTaskSbills = res.data.data;
}else{
this.$message({ showClose:true, message: tips.msg, type: 'error' });
}
this.load.list = false;
}).catch( err => this.load.list = false );
},
// XmTaskSbill
showEdit: function ( row,index ) {
this.editFormVisible = true;
this.editForm = Object.assign({}, row);
},
// XmTaskSbill
showAdd: function () {
this.addFormVisible = true;
//this.addForm=Object.assign({}, this.editForm);
},
afterAddSubmit(){
this.addFormVisible=false;
this.pageInfo.count=true;
this.getXmTaskSbills();
},
afterEditSubmit(){
this.editFormVisible=false;
},
//xmTaskSbill
selsChange: function (sels) {
this.sels = sels;
},
//xmTaskSbill
handleDel: function (row,index) {
this.$confirm('确认删除该记录吗?', '提示', {
type: 'warning'
}).then(() => {
this.load.del=true;
let params = { id: row.id };
delXmTaskSbill(params).then((res) => {
this.load.del=false;
var tips=res.data.tips;
if(tips.isOk){
this.pageInfo.count=true;
this.getXmTaskSbills();
}
this.$message({ showClose:true, message: tips.msg, type: tips.isOk?'success':'error' });
}).catch( err => this.load.del=false );
});
},
//xmTaskSbill
batchDel: function () {
this.$confirm('确认删除选中记录吗?', '提示', {
type: 'warning'
}).then(() => {
this.load.del=true;
batchDelXmTaskSbill(this.sels).then((res) => {
this.load.del=false;
var tips=res.data.tips;
if( tips.isOk ){
this.pageInfo.count=true;
this.getXmTaskSbills();
}
this.$message({ showClose:true, message: tips.msg, type: tips.isOk?'success':'error'});
}).catch( err => this.load.del=false );
});
},
rowClick: function(row, event, column){
this.$emit('row-click',row, event, column);// @row-click="rowClick"
},
initData: function(){
},
/**begin 自定义函数请在下面加**/
},//end methods
mounted() {
this.$nextTick(() => {
//initSimpleDicts('all',['sex','gradeLvl']).then(res=>this.dicts=res.data.data);
this.initData()
this.searchXmTaskSbills();
if(this.$refs.xmTaskSbillTable){
var clientRect=this.$refs.xmTaskSbillTable.$el.getBoundingClientRect();
var subHeight=70/1000 * window.innerHeight;
this.maxTableHeight = window.innerHeight -clientRect.y - this.$refs.xmTaskSbillTable.$el.offsetTop-subHeight;
}
});
}
}
</script>
<style scoped>
</style>

174
src/views/xm/core/xmTaskWorkload/XmTaskWorkloadEdit.vue

@ -0,0 +1,174 @@
<template>
<section class="page-container padding">
<el-row class="page-header">
</el-row>
<el-row class="page-main" :style="{overflowX:'auto',height:maxTableHeight+'px'}" ref="table">
<!--编辑界面 XmTaskWorkload 工时登记表-->
<el-form :model="editForm" label-width="120px" :rules="editFormRules" ref="editFormRef">
<el-form-item label="员工编号" prop="userid">
<el-input v-model="editForm.userid" placeholder="员工编号"></el-input>
</el-form-item>
<el-form-item label="姓名" prop="username">
<el-input v-model="editForm.username" placeholder="姓名"></el-input>
</el-form-item>
<el-form-item label="创建日期" prop="ctime">
<el-date-picker type="date" placeholder="选择日期" v-model="editForm.ctime" value-format="yyyy-MM-dd HH:mm:ss" format="yyyy-MM-dd"></el-date-picker>
</el-form-item>
<el-form-item label="业务对象主键任务编号" prop="taskId">
<el-input v-model="editForm.taskId" placeholder="业务对象主键任务编号"></el-input>
</el-form-item>
<el-form-item label="创建人编号" prop="cuserid">
<el-input v-model="editForm.cuserid" placeholder="创建人编号"></el-input>
</el-form-item>
<el-form-item label="业务日期yyyy-MM-dd" prop="bizDate">
<el-input v-model="editForm.bizDate" placeholder="业务日期yyyy-MM-dd"></el-input>
</el-form-item>
<el-form-item label="状态0-待确认,1-已确认,2-无效" prop="wstatus">
<el-input v-model="editForm.wstatus" placeholder="状态0-待确认,1-已确认,2-无效"></el-input>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="editForm.remark" placeholder="备注"></el-input>
</el-form-item>
<el-form-item label="任务类型-关联字典taskType" prop="ttype">
<el-input v-model="editForm.ttype" placeholder="任务类型-关联字典taskType"></el-input>
</el-form-item>
<el-form-item label="主键" prop="id">
<el-input-number v-model="editForm.id" :min="0" :max="200"></el-input-number>
</el-form-item>
<el-form-item label="结算单据编号" prop="sbillId">
<el-input v-model="editForm.sbillId" placeholder="结算单据编号"></el-input>
</el-form-item>
<el-form-item label="结算提交时间" prop="stime">
<el-date-picker type="date" placeholder="选择日期" v-model="editForm.stime" value-format="yyyy-MM-dd HH:mm:ss" format="yyyy-MM-dd"></el-date-picker>
</el-form-item>
<el-form-item label="结算状态0-无需结算,1-待结算2-已提交3-已通过4-已结算" prop="sstatus">
<el-input v-model="editForm.sstatus" placeholder="结算状态0-无需结算,1-待结算2-已提交3-已通过4-已结算"></el-input>
</el-form-item>
<el-form-item label="工时对应金额" prop="amt">
<el-input v-model="editForm.amt" placeholder="工时对应金额"></el-input>
</el-form-item>
<el-form-item label="结算金额" prop="samt">
<el-input v-model="editForm.samt" placeholder="结算金额"></el-input>
</el-form-item>
<el-form-item label="工时,一个task_id可多次提交,小时" prop="workload">
<el-input v-model="editForm.workload" placeholder="工时,一个task_id可多次提交,小时"></el-input>
</el-form-item>
</el-form>
</el-row>
<el-row class="page-bottom bottom-fixed">
<el-button @click.native="handleCancel">取消</el-button>
<el-button v-loading="load.edit" type="primary" @click.native="saveSubmit" :disabled="load.edit==true">提交</el-button>
</el-row>
</section>
</template>
<script>
import util from '@/common/js/util';//
import config from "@/common/config"; //import
import { getDicts,initSimpleDicts,initComplexDicts } from '@/api/mdp/meta/item';//
import { addXmTaskWorkload,editXmTaskWorkload } from '@/api/xm/core/xmTaskWorkload';
import { mapGetters } from 'vuex'
export default {
name:'xmTaskWorkloadEdit',
components: {
},
computed: {
...mapGetters([ 'userInfo' ]),
},
props:['xmTaskWorkload','visible','opType'],
watch: {
'xmTaskWorkload':function( xmTaskWorkload ) {
if(xmTaskWorkload){
this.editForm = xmTaskWorkload;
}
},
'visible':function(visible) {
if(visible==true){
this.initData()
}
}
},
data() {
return {
currOpType:'add',//add/edit
load:{ list: false, edit: false, del: false, add: false },//...
dicts:{},// params={categoryId:'all',itemCodes:['sex']} {sex: [{id:'1',name:''},{id:'2',name:''}]}
editFormRules: {
id: [
//{ required: true, message: '', trigger: 'blur' }
]
},
editForm: {
userid:'',username:'',ctime:'',taskId:'',cuserid:'',bizDate:'',wstatus:'',remark:'',ttype:'',id:'',sbillId:'',stime:'',sstatus:'',amt:'',samt:'',workload:''
},
maxTableHeight:300,
}//end return
},//end data
methods: {
// @cancel="editFormVisible=false"
handleCancel:function(){
this.$refs['editFormRef'].resetFields();
this.$emit('cancel');
},
//XmTaskWorkload @submit="afterEditSubmit"
saveSubmit: function () {
this.$refs.editFormRef.validate((valid) => {
if (valid) {
this.$confirm('确认提交吗?', '提示', {}).then(() => {
this.load.edit=true
let params = Object.assign({}, this.editForm);
var func=addXmTaskWorkload
if(this.currOpType=='edit'){
func=editXmTaskWorkload
}
func(params).then((res) => {
this.load.edit=false
var tips=res.data.tips;
if(tips.isOk){
this.editForm=res.data.data
this.initData()
this.currOpType="edit";
this.$emit('submit');// @submit="afterAddSubmit"
}
this.$notify({ showClose:true, message: tips.msg, type: tips.isOk?'success':'error' });
}).catch( err =>this.load.edit=false);
});
}else{
this.$notify({ showClose:true, message: "表单验证不通过,请修改表单数据再提交", type: 'error' });
}
});
},
initData: function(){
this.currOpType=this.opType
if(this.xmTaskWorkload){
this.editForm = Object.assign({},this.xmTaskWorkload);
}
if(this.opType=='edit'){
}else{
}
},
},//end method
mounted() {
this.$nextTick(() => {
//initSimpleDicts('all',['sex','gradeLvl']).then(res=>this.dicts=res.data.data);
this.initData()
this.maxTableHeight = util.calcTableMaxHeight(this.$refs.table.$el)
});
}
}
</script>
<style scoped>
</style>

260
src/views/xm/core/xmTaskWorkload/XmTaskWorkloadMng.vue

@ -0,0 +1,260 @@
<template>
<section class="page-container border padding">
<el-row>
<el-input v-model="filters.key" style="width: 20%;" placeholder="模糊查询"></el-input>
<el-button v-loading="load.list" :disabled="load.list==true" @click="searchXmTaskWorkloads" icon="el-icon-search">查询</el-button>
<el-button type="primary" @click="showAdd" icon="el-icon-plus"> </el-button>
<el-button type="danger" v-loading="load.del" @click="batchDel" :disabled="this.sels.length===0 || load.del==true" icon="el-icon-delete"></el-button>
</el-row>
<el-row class="padding-top">
<!--列表 XmTaskWorkload 工时登记表-->
<el-table ref="xmTaskWorkloadTable" :data="xmTaskWorkloads" :height="maxTableHeight" @sort-change="sortChange" highlight-current-row v-loading="load.list" border @selection-change="selsChange" @row-click="rowClick" style="width: 100%;">
<el-table-column type="selection" width="55" show-overflow-tooltip></el-table-column>
<el-table-column sortable type="index" width="55" show-overflow-tooltip></el-table-column>
<el-table-column prop="userid" label="员工编号" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="username" label="姓名" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="ctime" label="创建日期" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="taskId" label="业务对象主键任务编号" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="cuserid" label="创建人编号" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="bizDate" label="业务日期yyyy-MM-dd" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="wstatus" label="状态0-待确认,1-已确认,2-无效" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="remark" label="备注" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="ttype" label="任务类型-关联字典taskType" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="id" label="主键" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="sbillId" label="结算单据编号" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="stime" label="结算提交时间" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="sstatus" label="结算状态0-无需结算,1-待结算2-已提交3-已通过4-已结算" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="amt" label="工时对应金额" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="samt" label="结算金额" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column prop="workload" label="工时,一个task_id可多次提交,小时" min-width="80" show-overflow-tooltip></el-table-column>
<el-table-column label="操作" width="180" fixed="right">
<template scope="scope">
<el-button type="primary" @click="showEdit( scope.row,scope.$index)" icon="el-icon-edit"></el-button>
<el-button type="danger" @click="handleDel(scope.row,scope.$index)" icon="el-icon-delete"></el-button>
</template>
</el-table-column>
</el-table>
<el-pagination layout="total, sizes, prev, pager, 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>
<el-row>
<!--编辑 XmTaskWorkload 工时登记表界面-->
<el-drawer title="编辑工时登记表" :visible.sync="editFormVisible" size="60%" append-to-body :close-on-click-modal="false">
<xm-task-workload-edit op-type="edit" :xm-task-workload="editForm" :visible="editFormVisible" @cancel="editFormVisible=false" @submit="afterEditSubmit"></xm-task-workload-edit>
</el-drawer>
<!--新增 XmTaskWorkload 工时登记表界面-->
<el-drawer title="新增工时登记表" :visible.sync="addFormVisible" size="60%" append-to-body :close-on-click-modal="false">
<xm-task-workload-edit op-type="add" :visible="addFormVisible" @cancel="addFormVisible=false" @submit="afterAddSubmit"></xm-task-workload-edit>
</el-drawer>
</el-row>
</section>
</template>
<script>
import util from '@/common/js/util';//
import config from '@/common/config';//
import { getDicts,initSimpleDicts,initComplexDicts } from '@/api/mdp/meta/item';//
import { listXmTaskWorkload, delXmTaskWorkload, batchDelXmTaskWorkload } from '@/api/xm/core/xmTaskWorkload';
import XmTaskWorkloadEdit from './XmTaskWorkloadEdit';//
import { mapGetters } from 'vuex'
export default {
name:'xmTaskWorkloadMng',
components: {
XmTaskWorkloadEdit,
},
props:['visible'],
computed: {
...mapGetters(['userInfo']),
},
watch:{
visible(val){
if(val==true){
this.initData();
this.searchXmTaskWorkloads()
}
}
},
data() {
return {
filters: {
key: ''
},
xmTaskWorkloads: [],//
pageInfo:{//
total:0,//0>0
pageSize:10,//
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:{
//sex: [{id:'1',name:''},{id:'2',name:''}]
},// params={categoryId:'all',itemCodes:['sex']} {sex: [{id:'1',name:''},{id:'2',name:''}]}
addFormVisible: false,//xmTaskWorkload
addForm: {
userid:'',username:'',ctime:'',taskId:'',cuserid:'',bizDate:'',wstatus:'',remark:'',ttype:'',id:'',sbillId:'',stime:'',sstatus:'',amt:'',samt:'',workload:''
},
editFormVisible: false,//
editForm: {
userid:'',username:'',ctime:'',taskId:'',cuserid:'',bizDate:'',wstatus:'',remark:'',ttype:'',id:'',sbillId:'',stime:'',sstatus:'',amt:'',samt:'',workload:''
},
maxTableHeight:300,
}
},//end data
methods: {
handleSizeChange(pageSize) {
this.pageInfo.pageSize=pageSize;
this.getXmTaskWorkloads();
},
handleCurrentChange(pageNum) {
this.pageInfo.pageNum = pageNum;
this.getXmTaskWorkloads();
},
// obj.order=ascending/descending, asc/desc ; obj.prop=,
sortChange( obj ){
if(obj.order==null){
this.pageInfo.orderFields=[];
this.pageInfo.orderDirs=[];
}else{
var dir='asc';
if(obj.order=='ascending'){
dir='asc'
}else{
dir='desc';
}
this.pageInfo.orderFields=[util.toLine(obj.prop)];
this.pageInfo.orderDirs=[dir];
}
this.getXmTaskWorkloads();
},
searchXmTaskWorkloads(){
this.pageInfo.count=true;
this.getXmTaskWorkloads();
},
// XmTaskWorkload
getXmTaskWorkloads() {
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(",")
}
if(this.filters.key){
params.key=this.filters.key
}
this.load.list = true;
listXmTaskWorkload(params).then((res) => {
var tips=res.data.tips;
if(tips.isOk){
this.pageInfo.total = res.data.total;
this.pageInfo.count=false;
this.xmTaskWorkloads = res.data.data;
}else{
this.$notify({ showClose:true, message: tips.msg, type: 'error' });
}
this.load.list = false;
}).catch( err => this.load.list = false );
},
// XmTaskWorkload
showEdit: function ( row,index ) {
this.editFormVisible = true;
this.editForm = Object.assign({}, row);
},
// XmTaskWorkload
showAdd: function () {
this.addFormVisible = true;
//this.addForm=Object.assign({}, this.editForm);
},
afterAddSubmit(){
this.addFormVisible=false;
this.pageInfo.count=true;
this.getXmTaskWorkloads();
},
afterEditSubmit(){
this.editFormVisible=false;
},
//xmTaskWorkload
selsChange: function (sels) {
this.sels = sels;
},
//xmTaskWorkload
handleDel: function (row,index) {
this.$confirm('确认删除该记录吗?', '提示', {
type: 'warning'
}).then(() => {
this.load.del=true;
let params = { id:row.id };
delXmTaskWorkload(params).then((res) => {
this.load.del=false;
var tips=res.data.tips;
if(tips.isOk){
this.pageInfo.count=true;
this.getXmTaskWorkloads();
}
this.$notify({ showClose:true, message: tips.msg, type: tips.isOk?'success':'error' });
}).catch( err => this.load.del=false );
});
},
//xmTaskWorkload
batchDel: function () {
if(this.sels.length<=0){
return;
}
var params=this.sels.map(i=>{
return { id:i.id}
})
this.$confirm('确认删除选中记录吗?', '提示', {
type: 'warning'
}).then(() => {
this.load.del=true;
batchDelXmTaskWorkload(params).then((res) => {
this.load.del=false;
var tips=res.data.tips;
if( tips.isOk ){
this.pageInfo.count=true;
this.getXmTaskWorkloads();
}
this.$notify({ showClose:true, message: tips.msg, type: tips.isOk?'success':'error'});
}).catch( err => this.load.del=false );
});
},
rowClick: function(row, event, column){
this.editForm=row
this.$emit('row-click',row, event, column);// @row-click="rowClick"
},
initData: function(){
},
},//end methods
mounted() {
this.$nextTick(() => {
//initSimpleDicts('all',['sex','gradeLvl']).then(res=>this.dicts=res.data.data);
this.initData()
this.searchXmTaskWorkloads();
this.maxTableHeight = util.calcTableMaxHeight(this.$refs.xmTaskWorkloadTable.$el)
});
}
}
</script>
<style scoped>
</style>

22
src/views/xm/core/xmTestCase/XmTestCaseMng.vue

@ -3,7 +3,7 @@
<el-row>
<div>
<el-tag v-if=" filters.product " closable @close="clearProduct">{{this.filters.product.productName}}</el-tag>
<el-button v-else @click="showProductVisible" type="plian">选产品</el-button>
<xm-product-select v-else :link-project-id="filters.selProject?filters.selProject.id:null" @row-click="onProductSelected"></xm-product-select>
<el-button v-if=" !filters.menus || filters.menus.length==0" @click="showMenu"> 选择需求</el-button>
<el-tag v-else closable @close=" clearFiltersMenu(filters.menus[0])">{{filters.menus[0].menuName.substr(0,5)}}({{filters.menus.length}})</el-tag>
<el-input v-model="filters.key" style="width: 20%;" placeholder="模糊查询">
@ -22,12 +22,11 @@
trigger="click" >
<el-row>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">产品:</font><el-tag v-if=" filters.product " closable @close="clearProduct">{{this.filters.product.productName}}</el-tag>
<el-button v-else @click="showProductVisible" type="plian">选产品</el-button>
<font class="more-label-font" v-if="!xmProduct">产品:</font>
<xm-product-select :link-project-id="filters.selProject?filters.selProject.id:null" @row-click="onProductSelected"></xm-product-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" v-if="!selProject" >
<font class="more-label-font">项目:</font><el-tag v-if=" filters.selProject " closable @close="clearProject">{{this.filters.selProject.name}}</el-tag>
<el-button v-else @click="showProjectList" type="plian">选项目</el-button>
<xm-project-select :link-product-id="filters.product?filters.product.id:null" @row-click="onPorjectConfirm"></xm-project-select>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">需求:</font>
@ -108,9 +107,6 @@
<el-drawer title="新增测试用例" :visible.sync="addFormVisible" size="80%" append-to-body :close-on-click-modal="false">
<xm-test-case-add :xm-test-case="addForm" :visible="addFormVisible" @cancel="addFormVisible=false" @submit="afterAddSubmit"></xm-test-case-add>
</el-drawer>
<el-drawer title="选中项目" :visible.sync="selectProjectVisible" size="80%" append-to-body :close-on-click-modal="false">
<xm-project-list @project-confirm="onPorjectConfirm"></xm-project-list>
</el-drawer>
<el-drawer title="选中用户" :visible.sync="selectUserForFiltersVisible" size="80%" append-to-body :close-on-click-modal="false">
<xm-group-mng v-if="filters.selProject" :sel-project=" filters.selProject " :is-select-single-user="1" @user-confirm="onFiltersUserConfirm"></xm-group-mng>
</el-drawer>
@ -118,10 +114,6 @@
<el-drawer append-to-body title="需求选择" :visible.sync="menuVisible" size="80%" :close-on-click-modal="false">
<xm-menu-select :visible="menuVisible" :is-select-menu="true" :multi="true" @menus-selected="onSelectedMenus" ></xm-menu-select>
</el-drawer>
<el-drawer title="选择产品" :visible.sync="productSelectVisible" size="80%" append-to-body :close-on-click-modal="false">
<xm-product-select :isSelectProduct="true" :selProject="filters.selProject" :visible="productSelectVisible" @cancel="productSelectVisible=false" @selected="onProductSelected"></xm-product-select>
</el-drawer>
</section>
</template>
@ -134,9 +126,9 @@
import XmTestCaseEdit from './XmTestCaseEdit';//
import { mapGetters } from 'vuex'
import xmMenuSelect from '../xmMenu/XmMenuSelect';
import XmProductSelect from '../xmProduct/XmProductSelect';//
import XmProductSelect from '@/views/xm/core/components/XmProductSelect';//
import XmProjectList from '../xmProject/XmProjectList';
import XmProjectSelect from '@/views/xm/core/components/XmProjectSelect';
import XmGroupMng from '../xmGroup/XmGroupMng';
export default {
@ -448,7 +440,7 @@
components: {
'xm-test-case-add':XmTestCaseAdd,
'xm-test-case-edit':XmTestCaseEdit,
xmMenuSelect,XmProductSelect,XmProjectList,XmGroupMng
xmMenuSelect,XmProductSelect,XmProjectSelect,XmGroupMng
//
},
mounted() {

68
src/views/xm/core/xmTestCaseExec/XmTestCaseExecMng.vue

@ -2,8 +2,8 @@
<section class="page-container padding border">
<el-row v-if="!batchEditVisible">
<el-checkbox v-model="gstcVisible" >甘特图</el-checkbox>
<el-tag type="primary" v-if="this.filters.selProject && !selProject " closable @close="clearProject" @click="showProjectList">{{ this.filters.selProject.name }}</el-tag>
<el-button v-if="!this.filters.selProject" @click="showProjectList">选择项目</el-button>
<xm-product-select :auto-select="false" :link-project-id="filters.selProject" @row-click="onProductSelected"></xm-product-select>
<xm-project-select :auto-select="false" :link-product-id="filters.product?filters.product.id:null" @row-click="onPorjectConfirm"></xm-project-select>
<el-button v-if=" !filters.menus || filters.menus.length==0" @click="showMenu"> 选择需求</el-button>
<el-tag v-else closable @close="clearFiltersMenu(filters.menus[0])">{{filters.menus[0].menuName.substr(0,5)}}({{filters.menus.length}})</el-tag>
<el-input v-model="filters.key" style="width: 20%;" placeholder="模糊查询">
@ -20,12 +20,10 @@
trigger="click" >
<el-row>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">产品:</font><el-tag v-if=" filters.product " closable @close="clearProduct">{{this.filters.product.productName}}</el-tag>
<el-button v-else @click="showProductVisible" type="plian">选产品</el-button>
<xm-product-select :auto-select="false" :link-project-id="filters.selProject" @row-click="onProductSelected"></xm-product-select>
</el-col>
<el-col :span="24" style="padding-top:5px;" v-if="!selProject" >
<font class="more-label-font">项目:</font><el-tag v-if=" filters.selProject " closable @close="clearProject">{{this.filters.selProject.name}}</el-tag>
<el-button v-else @click="showProjectList" type="plian">选项目</el-button>
<xm-project-select :auto-select="false" :link-product-id="filters.product?filters.product.id:null" @row-click="onPorjectConfirm"></xm-project-select>
</el-col>
<el-col :span="24" style="padding-top:5px;">
<font class="more-label-font">需求:</font>
@ -169,9 +167,6 @@
<el-drawer title="选择用例" :visible.sync="xmTestCaseMngVisible" size="60%" append-to-body :close-on-click-modal="false">
<xm-test-case-mng :multi-select="true" :visible="xmTestCaseMngVisible" @selected="onCaseSelected"></xm-test-case-mng>
</el-drawer>
<el-drawer title="选中项目" :visible.sync="selectProjectVisible" size="80%" append-to-body :close-on-click-modal="false">
<xm-project-list @project-confirm="onPorjectConfirm"></xm-project-list>
</el-drawer>
<el-drawer append-to-body title="需求选择" :visible.sync="menuVisible" fullscreen size="80%" :close-on-click-modal="false">
<xm-menu-select :visible="menuVisible" :is-select-menu="true" :multi="true" @menus-selected="onSelectedMenus" ></xm-menu-select>
</el-drawer>
@ -194,10 +189,6 @@
<el-drawer title="缺陷列表" :visible.sync="bugsVisible" size="80%" append-to-body fullscreen :close-on-click-modal="false">
<xm-question-mng :xm-test-case="xmTestCase" :xm-test-case-exec="editForm" :sel-project="filters.selProject" :visible="bugsVisible" @cancel="bugsVisible=false" ></xm-question-mng>
</el-drawer>
<el-drawer title="选择产品" :visible.sync="productSelectVisible" size="80%" append-to-body :close-on-click-modal="false">
<xm-product-select :isSelectProduct="true" :selProject="filters.selProject" :visible="productSelectVisible" @cancel="productSelectVisible=false" @selected="onProductSelected"></xm-product-select>
</el-drawer>
<!--新增 XmQuestion xm_question界面-->
<el-drawer title="新增缺陷" :visible.sync="addBugVisible" size="60%" append-to-body :close-on-click-modal="false">
<xm-question-add :xm-test-case-exec="editForm" :xm-test-case="xmTestCase" :qtype="'bug'" :sel-project=" filters.selProject " :visible="addBugVisible" @cancel="addBugVisible=false"></xm-question-add>
@ -218,14 +209,14 @@
import XmTestCaseExecAdd from './XmTestCaseExecAdd';//
import XmTestCaseExecEdit from './XmTestCaseExecEdit';//
import XmTestCaseMng from '../xmTestCase/XmTestCaseMng';//
import XmProjectList from '../xmProject/XmProjectList';
import XmProjectSelect from '@/views/xm/core/components/XmProjectSelect';
import xmMenuSelect from '../xmMenu/XmMenuSelect';
import XmGroupMng from '../xmGroup/XmGroupMng';
import XmTaskList from '../xmTask/XmTaskList';
import XmTestCaseEdit from '../xmTestCase/XmTestCaseEdit';//
import XmQuestionMng from '../xmQuestion/XmQuestionMng';//
import XmQuestionAdd from '../xmQuestion/XmQuestionAdd';//
import XmProductSelect from '../xmProduct/XmProductSelect';//
import XmProductSelect from '@/views/xm/core/components/XmProductSelect';//
import XmGantt from '../components/xm-gantt';
import { mapGetters } from 'vuex'
@ -502,7 +493,7 @@
showCase(){
if(!this.filters.selProject){
this.$notify({showClose: true,message:"请先选择项目",type:"warning"});
this.nextAction="showCase"
nextAction="showCase"
this.showProjectList();
return;
}
@ -516,28 +507,28 @@
showProjectList:function(){
this.selectProjectVisible=true;
},
onPorjectConfirm:function(project){
onPorjectConfirm:function(nextAction,project){
this.filters.selProject=project
this.selectProjectVisible=false;
this.getXmTestCaseExecs();
if(this.nextAction=="showBatchEdit"){
if(nextAction=="showBatchEdit"){
this.showBatchEdit();
this.nextAction=""
}else if(this.nextAction=="showCase"){
nextAction=""
}else if(nextAction=="showCase"){
this.showCase();
this.nextAction=""
}else if(this.nextAction=="showAddBug"){
nextAction=""
}else if(nextAction=="showAddBug"){
this.showAddBug(this.editForm);
this.nextAction=""
}else if(this.nextAction=="showBugs"){
nextAction=""
}else if(nextAction=="showBugs"){
this.showBugs(this.editForm);
this.nextAction=""
}else if(this.nextAction=="showSelectTask"){
nextAction=""
}else if(nextAction=="showSelectTask"){
this.showSelectTask(this.editForm);
this.nextAction=""
}else if(this.nextAction=="showExecUsersForFilters"){
nextAction=""
}else if(nextAction=="showExecUsersForFilters"){
this.showExecUsersForFilters();
this.nextAction=""
nextAction=""
}
},
formatterExecStatus(row,column,cellValue, index){
@ -589,7 +580,7 @@
}
if( !this.filters.selProject ){
this.$notify({showClose: true, message:"请先选择项目", type: 'warning'});
this.nextAction="showBatchEdit"
nextAction="showBatchEdit"
this.showProjectList();
return ;
}
@ -641,7 +632,7 @@
},
showExecUsersForFilters:function(){
if(!this.filters.selProject){
this.nextAction="showExecUsersForFilters"
nextAction="showExecUsersForFilters"
this.showProjectList();
}else{
this.selectUserForFiltersVisible=true;
@ -654,8 +645,8 @@
}else{
this.filters.execUser=groupUsers[0]
}
if(this.nextAction=="showExecUsersForFilters"){
this.nextAction=""
if(nextAction=="showExecUsersForFilters"){
nextAction=""
}
this.selectUserForFiltersVisible=false
this.searchXmTestCaseExecs();
@ -677,7 +668,7 @@
this.editForm=row
if(this.filters.selProject==null){
this.$notify({showClose: true, message: "请先选项目", type: 'success' });
this.nextAction="showSelectTask"
nextAction="showSelectTask"
this.showProjectList();
return ;
@ -707,7 +698,7 @@
if(!this.filters.selProject){
this.$notify({showClose: true, message: "请先选项目", type: 'success' });
this.showProjectList();
this.nextAction="showBugs"
nextAction="showBugs"
return ;
}
if(row.caseId){
@ -724,7 +715,7 @@
if(!this.filters.selProject){
this.$notify({showClose: true, message: "请先选项目", type: 'success' });
this.nextAction="showAddBug"
nextAction="showAddBug"
this.showProjectList();
return ;
}
@ -747,10 +738,11 @@
components: {
'xm-test-case-exec-add':XmTestCaseExecAdd,
'xm-test-case-exec-edit':XmTestCaseExecEdit,
XmTestCaseMng,XmProjectList,xmMenuSelect,XmGroupMng,XmTaskList,XmTestCaseEdit,XmQuestionMng,XmQuestionAdd, XmGantt,XmProductSelect
XmTestCaseMng,XmProjectSelect,xmMenuSelect,XmGroupMng,XmTaskList,XmTestCaseEdit,XmQuestionMng,XmQuestionAdd, XmGantt,XmProductSelect
//
},
mounted() {
XmProjectSelectmounted() {
this.filters.selProject=this.selProject;
this.filters.execUser=this.userInfo;
this.$nextTick(() => {

Loading…
Cancel
Save