Browse Source

优化项目试图

master
陈裕财 5 years ago
parent
commit
cd20c597a1
  1. 28
      src/router/routes_xm.js
  2. 19
      src/views/xm/core/xmIteration/XmIterationForProjectComplex.vue
  3. 444
      src/views/xm/core/xmIteration/XmIterationInfo.vue
  4. 61
      src/views/xm/core/xmIteration/XmIterationInfoRoute.vue
  5. 6
      src/views/xm/core/xmMenu/XmMenuMng.vue
  6. 0
      src/views/xm/core/xmProduct/XmProductForProjectComplex.vue
  7. 445
      src/views/xm/core/xmProduct/XmProductInfo.vue
  8. 61
      src/views/xm/core/xmProduct/XmProductInfoRoute.vue
  9. 158
      src/views/xm/core/xmProduct/XmProductMng.vue
  10. 1008
      src/views/xm/core/xmProduct/XmProductOverview.vue
  11. 130
      src/views/xm/core/xmProduct/XmProductOverviewComplex.vue
  12. 59
      src/views/xm/core/xmProject/XmProjectForLink.vue
  13. 12
      src/views/xm/core/xmProject/XmProjectInfo.vue
  14. 2
      src/views/xm/core/xmTask/XmTaskMng.vue

28
src/router/routes_xm.js

@ -77,6 +77,17 @@ export default {
]
},
{
path: '/xm/core/xmProduct/XmProductInfoRoute',
component: _import('xm/core/xmProduct/XmProductInfoRoute'),
name: 'XmProductInfoRoute',
iconCls: 'fa el-icon-menu',
meta: {
title: '产品管理',
icon: 'project',
hidden:true
},
},
{
path: '/xm/core',
component: Layout,
@ -89,13 +100,23 @@ export default {
// leaf: true,//只有一个节点
children: [
{ path: 'xmProduct/XmProductComplex', component: _import('xm/core/xmProduct/XmProductComplex'), name: 'XmProductComplex', meta: { title: '产品总览' }},
{ path: 'xmProduct/XmProductMng', component: _import('xm/core/xmProduct/XmProductMng'), name: 'XmProductMng', meta: { title: '产品管理' }},
{ path: 'xmProduct/XmProductMng', component: _import('xm/core/xmProduct/XmProductMng'), name: 'XmProductMng', meta: { title: '产品管理' }},
{ path: 'xmMenu/XmMenuMng', component: _import('xm/core/xmMenu/XmMenuMng'), name: 'XmMenuMng', meta: { title: '故事管理' }},
{ path: 'xmMenuExchange/XmMenuExchangeMng', component: _import('xm/core/xmMenuExchange/XmMenuExchangeMng'), name: 'XmMenuExchangeMng', meta: { title: '互动评论' }},
{ path: 'xmMenuTemplate/XmMenuTemplateMng', component: _import('xm/core/xmMenuTemplate/XmMenuTemplateMng'), name: 'XmMenuTemplateMng', meta: { title: '故事模板' }},
]
},,
{
path: '/xm/core/xmIteration/XmIterationInfoRoute',
component: _import('xm/core/xmIteration/XmIterationInfoRoute'),
name: 'XmIterationInfoRoute',
iconCls: 'fa el-icon-menu',
meta: {
title: '迭代管理',
icon: 'project',
hidden:true
},
},
{
path: '/xm/core',
@ -108,8 +129,7 @@ export default {
},
// leaf: true,//只有一个节点
children: [
{ path: 'xmIteration/XmIterationComplex', component: _import('xm/core/xmIteration/XmIterationComplex'), name: 'XmIterationComplex', meta: { title: '迭代总览' }},
{ path: 'xmIteration/XmIterationMng', component: _import('xm/core/xmIteration/XmIterationMng'), name: 'XmIterationMng', meta: { title: '迭代管理' }},
{ path: 'xmIteration/XmIterationMng', component: _import('xm/core/xmIteration/XmIterationMng'), name: 'XmIterationMng', meta: { title: '迭代管理' }},
{ path: 'xmIterationMenu/XmIterationMenuMng', component: _import('xm/core/xmIterationMenu/XmIterationMenuMng'), name: 'XmIterationMenuMng', meta: { title: '故事迭代' }},
]
}

src/views/xm/core/xmIteration/XmIterationComplex.vue → src/views/xm/core/xmIteration/XmIterationForProjectComplex.vue

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

@ -0,0 +1,444 @@
<template>
<section class="page-container page-full-height">
<el-row>
<el-menu :default-active="infotype" mode="horizontal" @select="setInfotype" class="menus" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b">
<el-menu-item index="项目概览" >
<span slot="title" >
<span slot="title" @click.stop="goBack"><i class="el-icon-back" ></i></span>
<i class="el-icon-s-data"></i>
<font v-if="selProject.name.length>=10">{{selProject.name.substring(0,10)}}</font>
<font type="danger" v-else>{{selProject.name}}</font>
概览
</span>
</el-menu-item>
<el-menu-item index="迭代">
<span slot="title"><i class="el-icon-document-copy"></i>迭代</span>
</el-menu-item>
<el-menu-item index="产品">
<span slot="title"><i class="el-icon-s-flag"></i>产品</span>
</el-menu-item>
<el-menu-item label="故事" index="用户故事">
<span slot="title"><i class="el-icon-document"></i>故事</span>
</el-menu-item>
<el-menu-item index="任务">
<span slot="title"><i class="el-icon-s-operation"></i>任务</span>
</el-menu-item>
<el-menu-item index="缺陷">
<span slot="title"><i class="el-icon-question"></i>缺陷</span>
</el-menu-item>
<el-menu-item index="团队">
<span slot="title"><i class="el-icon-user-solid"></i>团队</span>
</el-menu-item>
<el-menu-item index="文档">
<span slot="title"><i class="el-icon-document"></i>文档</span>
</el-menu-item>
<el-submenu index="规划与里程碑">
<template slot="title">规划与里程碑 </template>
<el-menu-item index="阶段计划及里程碑">
<span slot="title"><i class="el-icon-odometer"></i>阶段计划及里程碑</span>
</el-menu-item>
<el-menu-item index="测试计划">
<span slot="title"><i class="el-icon-odometer"></i>测试计划</span>
</el-menu-item>
</el-submenu >
<el-menu-item index="项目监控" class="hidden-lg-and-down">
<span slot="title"><i class="el-icon-video-camera"></i>项目监控</span>
</el-menu-item>
<el-menu-item index="故事监控" class="hidden-lg-and-down">
<span slot="title"><i class="el-icon-video-camera"></i>故事监控</span>
</el-menu-item>
<el-menu-item index="合同管理" class="hidden-md-and-down">
<span slot="title"><i class="el-icon-s-data"></i>合同管理</span>
</el-menu-item>
<el-menu-item index="预算" class="hidden-md-and-down">
<span slot="title"><i class="el-icon-coin"></i>预算</span>
</el-menu-item>
<el-menu-item index="费用" class="hidden-md-and-down">
<span slot="title"><i class="el-icon-coin"></i>费用</span>
</el-menu-item>
<el-menu-item index="考核" class="hidden-lg-and-down">
<span slot="title"><i class="el-icon-view"></i>考核</span>
</el-menu-item>
<el-menu-item index="日志" class="hidden-lg-and-down">
<span slot="title"><i class="el-icon-edit-outline"></i>日志</span>
</el-menu-item>
<el-menu-item index="环境清单" class="hidden-lg-and-down">
<span slot="title"><i class="el-icon-setting"></i>环境清单</span>
</el-menu-item>
<el-menu-item index="风险" class="hidden-lg-and-down">
<span slot="title"><i class="el-icon-question"></i>风险</span>
</el-menu-item>
<el-submenu index="更多">
<template slot="title">更多 </template>
<el-menu-item index="故事监控" >
<span slot="title"><i class="el-icon-video-camera"></i>故事监控</span>
</el-menu-item>
<el-menu-item index="项目监控">
<span slot="title"><i class="el-icon-video-camera"></i>项目监控</span>
</el-menu-item>
<el-menu-item index="预算">
<span slot="title"><i class="el-icon-coin"></i>预算</span>
</el-menu-item>
<el-menu-item index="费用">
<span slot="title"><i class="el-icon-coin"></i>费用</span>
</el-menu-item>
<el-menu-item index="考核">
<span slot="title"><i class="el-icon-view"></i>考核</span>
</el-menu-item>
<el-menu-item index="日志">
<span slot="title"><i class="el-icon-edit-outline"></i>日志</span>
</el-menu-item>
<el-menu-item index="合同管理">
<span slot="title"><i class="el-icon-s-data"></i>合同管理</span>
</el-menu-item>
<el-menu-item index="环境清单">
<span slot="title"><i class="el-icon-setting"></i>环境清单</span>
</el-menu-item>
<el-menu-item index="风险">
<span slot="title"><i class="el-icon-question"></i>风险</span>
</el-menu-item>
<el-menu-item index="论坛">
<span slot="title"><i class="el-icon-date"></i>论坛</span>
</el-menu-item>
<el-menu-item index="即聊">
<span slot="title"><i class="el-icon-date"></i>即聊</span>
</el-menu-item>
<el-menu-item index="客服">
<span slot="title"><i class="el-icon-date"></i>客服</span>
</el-menu-item>
</el-submenu>
</el-menu>
<xm-project-overview-complex v-if="infotype=='项目概览'" :sel-project="selProject"></xm-project-overview-complex>
<xm-iteration-for-project-complex v-if="infotype=='迭代'" ref="xmIterationMng" :sel-project="selProject"></xm-iteration-for-project-complex>
<xm-product-for-project-complex v-if="infotype=='产品'" ref="xmProductComplex" :sel-project="selProject"></xm-product-for-project-complex>
<xm-menu-mng v-if="infotype=='用户故事'" :sel-project="selProject"></xm-menu-mng>
<xm-task-mng v-if="infotype=='任务'" ref="xmTaskMng" :sel-project="selProject" ></xm-task-mng>
<xm-question v-if="infotype=='缺陷'" :qtype="'bug'" :sel-project='selProject' ref="xmQuestion"></xm-question>
<xm-group-mng v-if="infotype=='团队'" :sel-project="selProject"></xm-group-mng>
<xm-file-mng v-if="infotype=='文档'" :sel-project="selProject"></xm-file-mng>
<xm-project-phase-mng v-if="infotype=='阶段计划及里程碑'" ref="xmProjectPhaseMng" :sel-project="selProject" ></xm-project-phase-mng>
<xm-test-case-exec-mng v-if="infotype=='测试计划'" :visible="infotype=='测试计划'" :sel-project='selProject' ref="xmQuestion"></xm-test-case-exec-mng>
<xm-menu-with-plan v-if="infotype=='故事监控'" ref="xmMenuWithPlan" :sel-project="selProject"></xm-menu-with-plan>
<xm-project-state-mng v-if="infotype=='项目监控'" :sel-project="selProject"></xm-project-state-mng>
<xm-budget v-if="infotype=='预算'" :sel-project="selProject"></xm-budget>
<xm-cost v-if="infotype=='费用'" :sel-project="selProject"></xm-cost>
<xm-project-kpi v-if="infotype=='考核'" :sel-project="selProject"></xm-project-kpi>
<xm-record v-if="infotype=='日志'" :visible="infotype=='日志'" :sel-project="selProject"></xm-record>
<xm-contract v-if="infotype=='合同管理'" :sel-project="selProject"></xm-contract>
<xm-env-list v-if="infotype=='环境清单'" :sel-project="selProject"></xm-env-list>
<xm-question v-if="infotype=='风险'" :qtype="'risk'" :sel-project='selProject' ref="xmRisk"></xm-question>
<el-drawer title="选中团队成员" :visible.sync="groupUserVisible" size="50%" append-to-body :close-on-click-modal="false">
<xm-project-group-select :sel-project="selProject" :visible="groupUserVisible" is-select-multi-user="1" @user-confirm="onUserSelected"></xm-project-group-select>
</el-drawer>
</el-row>
</section>
</template>
<script>
import util from '@/common/js/util';//
//import Sticky from '@/components/Sticky' // header
//import { listOption } from '@/api/mdp/meta/itemOption';//
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 '../xmProjectGroup/XmProjectGroupMng';
import xmProjectGroupSelect from '../xmProjectGroup/XmProjectGroupSelect';
import xmExchange from '../xmExchange/XmExchangeMng';
import xmQuestion from '../xmQuestion/XmQuestionMng';
import xmFileMng from '../xmFile/XmFileMng';
import xmDetail from '../xmProject/XmProjectDetail';
import xmProjectKpi from '../xmProjectKpi/XmProjectKpiMng';
import xmRecord from '../xmRecord/XmRecordMng';
import xmCost from '../xmProject/XmProjectCost';
import xmBudget from '../xmProject/XmProjectBudgetCost';
import xmContract from '../xmProjectContract/XmProjectContractMng';
import xmEnvList from '../xmProjectEnvList/XmProjectEnvListMng';
import xmProjectPhaseMng from '../xmProjectPhase/XmProjectPhaseMng';
import xmMenuMng from '../xmMenu/XmMenuMng';
import xmMenuWithPlan from '../xmMenu/XmMenuWithPlan';
import xmProjectStateMng from '../xmProjectState/XmProjectStateMng';
import xmTestCaseExecMng from '../xmTestCaseExec/XmTestCaseExecMng';
import XmIterationForProjectComplex from '../xmIteration/XmIterationForProjectComplex.vue';
import XmProjectOverviewComplex from '../xmProject/XmProjectOverviewComplex.vue';
import XmProductForProjectComplex from '../xmProduct/XmProductForProjectComplex.vue';
export default {
props: ["selProject","visible"],
computed: {
...mapGetters([
'userInfo','roles'
]),
},
watch:{
selProject:function(selProject){
var oldInfotype=this.infotype
this.infotype=''
this.$nextTick(()=>{
this.infotype=oldInfotype
})
}
},
data() {
return {
platformViewVisible:false,
tabPosition:'left',
infotype:"项目概览",
load:{list:false,edit:false},
groupUserVisible:false,
exportArr: ['任务', '阶段计划', '故事监控']
/**end 自定义属性请在上面加 请加备注**/
}
},//end data
methods: {
afterEditSubmit:function(project){
this.$emit("submit",project)
},
toArchive:function(){
this.$router.push({
path: "/mdp/arc/mate/archive/ArchiveMng"
});
},
toIm:function(){
this.groupUserVisible=true
},
toHelpMe:function(){
this.$router.push({
path: "/mdp/im/messages/crmChat",
query:{
categoryId:'css',
sendContent:'咨询'
}
});
},
handleMenuSelect(menuId){
this.infotype=menuId
},
onUserSelected:function(users){
if(this.groupUserVisible==true){
var query={}
if(users){
if( users.length==1 ){
var user=users[0]
query.toUserid=user.userid
query.toUsername=user.username
query.msgType="prichat"
}else if( users.length >=2 ){
query.users=JSON.stringify(users.map(i=>{return {userid:i.userid,username:i.username}}))
query.categoryId="common"
query.msgType="group"
}
}
this.$router.push({
path: "/mdp/im/messages/messageChat",
query: query
});
}
},
setInfotype(infotype){
this.infotype=infotype;
},
handleExport() {
this.downloadLoading = true
let list = [];
let header = [];
let keyList = [];
let pageNum = 1;
let infotypeKey = '';
if (this.infotype === '任务') {
header = ['序号', '任务名称', '故事', '预算(万)', '工作量(人时)', '执行人', '进度', '任务开始时间', '任务结束时间', '任务技能需求'];
keyList = ['sortLevel', 'name', 'menuName', 'budgetCost', 'budgetWorkload', 'exeUsernames', 'rate', 'startTime', 'endTime', 'taskSkillNames'];
list = this.$refs.xmTaskMng.tasksTreeData;
pageNum = this.$refs.xmTaskMng.pageInfo.pageNum;
} else if (this.infotype === '阶段计划') {
header = ['序号', '阶段名称', '开始时间', '结束时间', '进度(%)', '状态', '计划人数', '实际人数', '计划工期', '实际工期', '计划工作量(人时)', '实际工作量(人时)', '计划非人力成本(元)', '实际非人力成本(元)', '计划内购人力成本(元)', '实际内购人力成本(元)', '计划外购人力成本(元)', '实际外购人力成本(元)', '计划成本合计(元)', '实际成本合计(元)', '审批状态', '备注'];
keyList = ['seqNo', 'phaseName', 'beginDate', 'endDate', 'actRate', 'phaseStatus', 'phaseBudgetOutUserCnt', 'actStaffNu', 'phaseBudgetHours', 'actHours', 'phaseBudgetWorkload', 'phaseActWorkload', 'phaseBudgetNouserAt', 'actNouserAt', 'phaseBudgetInnerUserAt', 'actInnerUserAt', 'phaseBudgetOutUserAt', 'actOutUserAt', 'phaseBudgetCostAt', 'actCostAt', 'bizFlowState', 'remark'];
list = this.$refs.xmProjectPhaseMng.projectPhaseTreeData;
pageNum = this.$refs.xmProjectPhaseMng.pageInfo.pageNum;
} else if (this.infotype === '故事监控') {
header = ['序号', '故事名称', '计划状态', '负责人', '上线时间', '计划开始时间', '实际开始时间', '计划结束时间', '实际结束时间', '计划工作量(人时)', '实际工作量(人时)', '计划成本(元)', '实际成本(元)', '总体完成比例%', '需求完成比例%', '设计完成比例%', '开发完成比例%', 'sit完成比例%', 'uat完成比例%', '上线状态'];
keyList = ['seqNo', 'menuName', 'planStatus', 'chargeUsername', 'onlineTime', 'planStartTime', 'actStartTime', 'planEndTime', 'actEndTime', 'planWorkload', 'actWorkload', 'planCostAmount', 'actCostAmount', 'finishRate', 'demandRate', 'designRate', 'devRate', 'sitRate', 'uatRate', 'onlineStatus'];
list = this.$refs.xmMenuWithPlan.xmMenusTreeData;
pageNum = this.$refs.xmMenuWithPlan.pageInfo.pageNum;
}
const filename = `${this.selProject.name}_${this.infotype}_第${pageNum}`;
const data = this.formatJson(keyList, list);
import('@/vendor/Export2Excel').then(excel => {
excel.export_json_to_excel({
header,
data,
filename,
// autoWidth: this.autoWidth,
bookType: 'xlsx'
})
this.downloadLoading = false
})
},
formatJson(filterVal, jsonData, dataList = []) {
if (this.infotype == '任务') {
jsonData.forEach(v => {
const row = filterVal.map(j => {
let key = '';
return v[j];
})
dataList.push(row);
if (v.children && v.children.length) {
dataList = this.formatJson(filterVal, v.children, dataList);
}
})
return dataList;
} else if (this.infotype == '阶段计划') {
const bizFlowStateDict = {
0: '未发审',
1: '审核中',
2: '已通过',
3: '未通过',
4: '已取消'
}
jsonData.forEach(v => {
const row = filterVal.map(j => {
let key = '';
if(j == 'phaseStatus') {
return this.$refs.xmProjectPhaseMng.formateOption('xmPhaseStatus', v.phaseStatus);
} else if(j == 'bizFlowState') {
return `${bizFlowStateDict[parseInt(v[j]) || 0]}`;
} else {
return v[j];
}
})
dataList.push(row);
if (v.children && v.children.length) {
dataList = this.formatJson(filterVal, v.children, dataList);
}
})
return dataList;
} else if (this.infotype == '故事监控') {
jsonData.forEach(v => {
const row = filterVal.map(j => {
let key = '';
if(j == 'planStatus') {
key = 'xmMenuPlanStatus';
} else if(j == 'onlineStatus') {
return parseInt(v[j]) ? '已上线' : '未上线';
} else {
return v[j];
}
const options = this.$refs.xmMenuWithPlan.options;
if(options[key]==undefined || options[key]==null || options[key].length==0 ){
return v[j];
}
var rowData=options[key].filter(i=>i.optionValue==v[j])
if(rowData.length>0){
return rowData[0].optionName
}else{
return v[j];
}
});
dataList.push(row);
if (v.children && v.children.length) {
dataList = this.formatJson(filterVal, v.children, dataList);
}
})
return dataList;
}
},
getDateString(dateStr){
if(dateStr==null || dateStr=="" || dateStr==undefined){
return ""
}else{
return dateStr.substr(0,10);
}
},
goBack(){
this.$router.back()
}
},//end methods
components: {
xmTaskMng,
xmProjectPhaseMng,
xmGroupMng,
xmExchange,
xmQuestion,
xmFileMng,
xmDetail,
xmProjectKpi,
xmRecord,
xmCost,
xmBudget,
xmContract,
xmEnvList,
xmMenuMng,
xmMenuWithPlan,
xmProjectStateMng,
xmTestCaseExecMng,
xmProjectGroupSelect,
XmIterationForProjectComplex,
XmProjectOverviewComplex,
XmProductForProjectComplex,
//
},
mounted() {
this.$nextTick(() => {
});
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.menus{
.el-menu-item{
padding-left: 0px !important;
}
}
/* 超过宽度则用...代替 */
.truncate{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>

61
src/views/xm/core/xmIteration/XmIterationInfoRoute.vue

@ -0,0 +1,61 @@
<template>
<section>
<xm-iteration-info v-if="xmIteration" :xm-iteration="xmIteration" :visible="showInfo"></xm-iteration-info>
</section>
</template>
<script>
import util from '@/common/js/util';//
import { mapGetters } from 'vuex';
import XmIterationInfo from './XmIterationInfo'
export default {
computed: {
...mapGetters([
'userInfo','roles'
]),
},
watch:{
},
data() {
return {
xmIteration:null,
showInfo:false,
}
},//end data
methods: {
},//end methods
components: {
XmIterationInfo,
//
},
activated(){
if(this.$route.params && this.$route.params.id){
this.xmIteration=this.$route.params
this.showInfo=true;
localStorage.setItem('xm-iteration-info-route',JSON.stringify(this.xmIteration));
}else{
this.xmIteration=JSON.parse(localStorage.getItem("xm-iteration-info-route"))
this.showInfo=true;
}
},
mounted() {
if(this.$route.params && this.$route.params.id){
this.xmIteration=this.$route.params
this.showInfo=true;
localStorage.setItem('xm-iteration-info-route',JSON.stringify(this.xmIteration));
}else{
this.xmIteration=JSON.parse(localStorage.getItem("xm-iteration-info-route"))
this.showInfo=true;
}
}
}
</script>
<style scoped>
</style>

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

@ -27,8 +27,8 @@
</el-input>
<el-button type="primary" v-loading="load.list" :disabled="load.list==true" v-on:click="searchXmMenus" icon="el-icon-search"></el-button>
<el-button type="primary" @click="showAdd" icon="el-icon-plus">故事</el-button>
<el-button @click="toBatchEdit" icon="el-icon-edit">修改</el-button>
<el-button v-if="!selProject&&!xmIteration" type="primary" @click="showAdd" icon="el-icon-plus">故事</el-button>
<el-button v-if="!selProject&&!xmIteration" @click="toBatchEdit" icon="el-icon-edit">修改</el-button>
<el-popover
placement="top-start"
title=""
@ -110,7 +110,7 @@
<el-tag slot="reference" icon="el-icon-chat-line-square">描述</el-tag>
</el-popover>
<el-button size="mini" type="primary" @click="showSubAdd( scope.row,scope.$index)" icon="el-icon-plus" circle></el-button>
<el-button v-if="!selProject&&!xmIteration" size="mini" type="primary" @click="showSubAdd( scope.row,scope.$index)" icon="el-icon-plus" circle></el-button>
<el-popover style="padding-left:10px;"
v-if="isPmUser"

src/views/xm/core/xmProduct/XmProductComplex.vue → src/views/xm/core/xmProduct/XmProductForProjectComplex.vue

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

@ -0,0 +1,445 @@
<template>
<section class="page-container page-full-height">
<el-row>
<el-menu :default-active="infotype" mode="horizontal" @select="setInfotype" class="menus" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b">
<el-menu-item index="产品概览" >
<span slot="title" >
<span slot="title" @click.stop="goBack"><i class="el-icon-back" ></i></span>
<i class="el-icon-s-data"></i>
<font v-if="xmProduct.productName.length>=10">{{xmProduct.productName.substring(0,10)}}</font>
<font type="danger" v-else>{{xmProduct.productName}}</font>
概览
</span>
</el-menu-item>
<el-menu-item index="迭代">
<span slot="title"><i class="el-icon-document-copy"></i>迭代</span>
</el-menu-item>
<el-menu-item label="项目" index="项目">
<span slot="title"><i class="el-icon-document"></i>项目</span>
</el-menu-item>
<el-menu-item label="故事" index="用户故事">
<span slot="title"><i class="el-icon-document"></i>故事</span>
</el-menu-item>
<el-menu-item index="任务">
<span slot="title"><i class="el-icon-s-operation"></i>任务</span>
</el-menu-item>
<el-menu-item index="缺陷">
<span slot="title"><i class="el-icon-question"></i>缺陷</span>
</el-menu-item>
<el-menu-item index="团队">
<span slot="title"><i class="el-icon-user-solid"></i>团队</span>
</el-menu-item>
<el-menu-item index="文档">
<span slot="title"><i class="el-icon-document"></i>文档</span>
</el-menu-item>
<el-submenu index="规划与里程碑">
<template slot="title">规划与里程碑 </template>
<el-menu-item index="阶段计划及里程碑">
<span slot="title"><i class="el-icon-odometer"></i>阶段计划及里程碑</span>
</el-menu-item>
<el-menu-item index="测试计划">
<span slot="title"><i class="el-icon-odometer"></i>测试计划</span>
</el-menu-item>
</el-submenu >
<el-menu-item index="项目监控" class="hidden-lg-and-down">
<span slot="title"><i class="el-icon-video-camera"></i>项目监控</span>
</el-menu-item>
<el-menu-item index="故事监控" class="hidden-lg-and-down">
<span slot="title"><i class="el-icon-video-camera"></i>故事监控</span>
</el-menu-item>
<el-menu-item index="合同管理" class="hidden-md-and-down">
<span slot="title"><i class="el-icon-s-data"></i>合同管理</span>
</el-menu-item>
<el-menu-item index="预算" class="hidden-md-and-down">
<span slot="title"><i class="el-icon-coin"></i>预算</span>
</el-menu-item>
<el-menu-item index="费用" class="hidden-md-and-down">
<span slot="title"><i class="el-icon-coin"></i>费用</span>
</el-menu-item>
<el-menu-item index="考核" class="hidden-lg-and-down">
<span slot="title"><i class="el-icon-view"></i>考核</span>
</el-menu-item>
<el-menu-item index="日志" class="hidden-lg-and-down">
<span slot="title"><i class="el-icon-edit-outline"></i>日志</span>
</el-menu-item>
<el-menu-item index="环境清单" class="hidden-lg-and-down">
<span slot="title"><i class="el-icon-setting"></i>环境清单</span>
</el-menu-item>
<el-menu-item index="风险" class="hidden-lg-and-down">
<span slot="title"><i class="el-icon-question"></i>风险</span>
</el-menu-item>
<el-submenu index="更多">
<template slot="title">更多 </template>
<el-menu-item index="故事监控" >
<span slot="title"><i class="el-icon-video-camera"></i>故事监控</span>
</el-menu-item>
<el-menu-item index="项目监控">
<span slot="title"><i class="el-icon-video-camera"></i>项目监控</span>
</el-menu-item>
<el-menu-item index="预算">
<span slot="title"><i class="el-icon-coin"></i>预算</span>
</el-menu-item>
<el-menu-item index="费用">
<span slot="title"><i class="el-icon-coin"></i>费用</span>
</el-menu-item>
<el-menu-item index="考核">
<span slot="title"><i class="el-icon-view"></i>考核</span>
</el-menu-item>
<el-menu-item index="日志">
<span slot="title"><i class="el-icon-edit-outline"></i>日志</span>
</el-menu-item>
<el-menu-item index="合同管理">
<span slot="title"><i class="el-icon-s-data"></i>合同管理</span>
</el-menu-item>
<el-menu-item index="环境清单">
<span slot="title"><i class="el-icon-setting"></i>环境清单</span>
</el-menu-item>
<el-menu-item index="风险">
<span slot="title"><i class="el-icon-question"></i>风险</span>
</el-menu-item>
<el-menu-item index="论坛">
<span slot="title"><i class="el-icon-date"></i>论坛</span>
</el-menu-item>
<el-menu-item index="即聊">
<span slot="title"><i class="el-icon-date"></i>即聊</span>
</el-menu-item>
<el-menu-item index="客服">
<span slot="title"><i class="el-icon-date"></i>客服</span>
</el-menu-item>
</el-submenu>
</el-menu>
<xm-product-overview-complex v-if="infotype=='产品概览'" :xm-product="xmProduct"></xm-product-overview-complex>
<xm-iteration-for-project-complex v-if="infotype=='迭代'" ref="xmIterationMng" :xm-product="xmProduct"></xm-iteration-for-project-complex>
<xm-project-for-link v-if="infotype=='项目'" ref="xmProjectForLink" :xm-product="xmProduct"></xm-project-for-link>
<xm-menu-mng v-if="infotype=='用户故事'" :xm-product="xmProduct"></xm-menu-mng>
<xm-task-mng v-if="infotype=='任务'" ref="xmTaskMng" :xm-product="xmProduct" ></xm-task-mng>
<xm-question v-if="infotype=='缺陷'" :qtype="'bug'" :xm-product='xmProduct' ref="xmQuestion"></xm-question>
<xm-group-mng v-if="infotype=='团队'" :xm-product="xmProduct"></xm-group-mng>
<xm-file-mng v-if="infotype=='文档'" :xm-product="xmProduct"></xm-file-mng>
<xm-project-phase-mng v-if="infotype=='阶段计划及里程碑'" ref="xmProjectPhaseMng" :xm-product="xmProduct" ></xm-project-phase-mng>
<xm-test-case-exec-mng v-if="infotype=='测试计划'" :visible="infotype=='测试计划'" :xm-product='xmProduct' ref="xmQuestion"></xm-test-case-exec-mng>
<xm-menu-with-plan v-if="infotype=='故事监控'" ref="xmMenuWithPlan" :xm-product="xmProduct"></xm-menu-with-plan>
<xm-project-state-mng v-if="infotype=='项目监控'" :xm-product="xmProduct"></xm-project-state-mng>
<xm-budget v-if="infotype=='预算'" :xm-product="xmProduct"></xm-budget>
<xm-cost v-if="infotype=='费用'" :xm-product="xmProduct"></xm-cost>
<xm-project-kpi v-if="infotype=='考核'" :xm-product="xmProduct"></xm-project-kpi>
<xm-record v-if="infotype=='日志'" :visible="infotype=='日志'" :xm-product="xmProduct"></xm-record>
<xm-contract v-if="infotype=='合同管理'" :xm-product="xmProduct"></xm-contract>
<xm-env-list v-if="infotype=='环境清单'" :xm-product="xmProduct"></xm-env-list>
<xm-question v-if="infotype=='风险'" :qtype="'risk'" :xm-product='xmProduct' ref="xmRisk"></xm-question>
<el-drawer title="选中团队成员" :visible.sync="groupUserVisible" size="50%" append-to-body :close-on-click-modal="false">
<xm-project-group-select :xm-product="xmProduct" :visible="groupUserVisible" is-select-multi-user="1" @user-confirm="onUserSelected"></xm-project-group-select>
</el-drawer>
</el-row>
</section>
</template>
<script>
import util from '@/common/js/util';//
//import Sticky from '@/components/Sticky' // header
//import { listOption } from '@/api/mdp/meta/itemOption';//
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 '../xmProjectGroup/XmProjectGroupMng';
import xmProjectGroupSelect from '../xmProjectGroup/XmProjectGroupSelect';
import xmExchange from '../xmExchange/XmExchangeMng';
import xmQuestion from '../xmQuestion/XmQuestionMng';
import xmFileMng from '../xmFile/XmFileMng';
import xmDetail from '../xmProject/XmProjectDetail';
import xmProjectKpi from '../xmProjectKpi/XmProjectKpiMng';
import xmRecord from '../xmRecord/XmRecordMng';
import xmCost from '../xmProject/XmProjectCost';
import xmBudget from '../xmProject/XmProjectBudgetCost';
import xmContract from '../xmProjectContract/XmProjectContractMng';
import xmEnvList from '../xmProjectEnvList/XmProjectEnvListMng';
import xmProjectPhaseMng from '../xmProjectPhase/XmProjectPhaseMng';
import xmMenuMng from '../xmMenu/XmMenuMng';
import xmMenuWithPlan from '../xmMenu/XmMenuWithPlan';
import xmProjectStateMng from '../xmProjectState/XmProjectStateMng';
import xmTestCaseExecMng from '../xmTestCaseExec/XmTestCaseExecMng';
import XmIterationForProjectComplex from '../xmIteration/XmIterationForProjectComplex.vue';
import XmProductOverviewComplex from '../xmProduct/XmProductOverviewComplex.vue';
import XmProductForProjectComplex from './XmProductForProjectComplex.vue';
import XmProjectForLink from '../xmProject/XmProjectForLink.vue';
export default {
props: ["xmProduct","visible"],
computed: {
...mapGetters([
'userInfo','roles'
]),
},
watch:{
xmProduct:function(xmProduct){
var oldInfotype=this.infotype
this.infotype=''
this.$nextTick(()=>{
this.infotype=oldInfotype
})
}
},
data() {
return {
platformViewVisible:false,
tabPosition:'left',
infotype:"项目概览",
load:{list:false,edit:false},
groupUserVisible:false,
exportArr: ['任务', '阶段计划', '故事监控']
/**end 自定义属性请在上面加 请加备注**/
}
},//end data
methods: {
afterEditSubmit:function(project){
this.$emit("submit",project)
},
toArchive:function(){
this.$router.push({
path: "/mdp/arc/mate/archive/ArchiveMng"
});
},
toIm:function(){
this.groupUserVisible=true
},
toHelpMe:function(){
this.$router.push({
path: "/mdp/im/messages/crmChat",
query:{
categoryId:'css',
sendContent:'咨询'
}
});
},
handleMenuSelect(menuId){
this.infotype=menuId
},
onUserSelected:function(users){
if(this.groupUserVisible==true){
var query={}
if(users){
if( users.length==1 ){
var user=users[0]
query.toUserid=user.userid
query.toUsername=user.username
query.msgType="prichat"
}else if( users.length >=2 ){
query.users=JSON.stringify(users.map(i=>{return {userid:i.userid,username:i.username}}))
query.categoryId="common"
query.msgType="group"
}
}
this.$router.push({
path: "/mdp/im/messages/messageChat",
query: query
});
}
},
setInfotype(infotype){
this.infotype=infotype;
},
handleExport() {
this.downloadLoading = true
let list = [];
let header = [];
let keyList = [];
let pageNum = 1;
let infotypeKey = '';
if (this.infotype === '任务') {
header = ['序号', '任务名称', '故事', '预算(万)', '工作量(人时)', '执行人', '进度', '任务开始时间', '任务结束时间', '任务技能需求'];
keyList = ['sortLevel', 'name', 'menuName', 'budgetCost', 'budgetWorkload', 'exeUsernames', 'rate', 'startTime', 'endTime', 'taskSkillNames'];
list = this.$refs.xmTaskMng.tasksTreeData;
pageNum = this.$refs.xmTaskMng.pageInfo.pageNum;
} else if (this.infotype === '阶段计划') {
header = ['序号', '阶段名称', '开始时间', '结束时间', '进度(%)', '状态', '计划人数', '实际人数', '计划工期', '实际工期', '计划工作量(人时)', '实际工作量(人时)', '计划非人力成本(元)', '实际非人力成本(元)', '计划内购人力成本(元)', '实际内购人力成本(元)', '计划外购人力成本(元)', '实际外购人力成本(元)', '计划成本合计(元)', '实际成本合计(元)', '审批状态', '备注'];
keyList = ['seqNo', 'phaseName', 'beginDate', 'endDate', 'actRate', 'phaseStatus', 'phaseBudgetOutUserCnt', 'actStaffNu', 'phaseBudgetHours', 'actHours', 'phaseBudgetWorkload', 'phaseActWorkload', 'phaseBudgetNouserAt', 'actNouserAt', 'phaseBudgetInnerUserAt', 'actInnerUserAt', 'phaseBudgetOutUserAt', 'actOutUserAt', 'phaseBudgetCostAt', 'actCostAt', 'bizFlowState', 'remark'];
list = this.$refs.xmProjectPhaseMng.projectPhaseTreeData;
pageNum = this.$refs.xmProjectPhaseMng.pageInfo.pageNum;
} else if (this.infotype === '故事监控') {
header = ['序号', '故事名称', '计划状态', '负责人', '上线时间', '计划开始时间', '实际开始时间', '计划结束时间', '实际结束时间', '计划工作量(人时)', '实际工作量(人时)', '计划成本(元)', '实际成本(元)', '总体完成比例%', '需求完成比例%', '设计完成比例%', '开发完成比例%', 'sit完成比例%', 'uat完成比例%', '上线状态'];
keyList = ['seqNo', 'menuName', 'planStatus', 'chargeUsername', 'onlineTime', 'planStartTime', 'actStartTime', 'planEndTime', 'actEndTime', 'planWorkload', 'actWorkload', 'planCostAmount', 'actCostAmount', 'finishRate', 'demandRate', 'designRate', 'devRate', 'sitRate', 'uatRate', 'onlineStatus'];
list = this.$refs.xmMenuWithPlan.xmMenusTreeData;
pageNum = this.$refs.xmMenuWithPlan.pageInfo.pageNum;
}
const filename = `${this.xmProduct.productName}_${this.infotype}_第${pageNum}`;
const data = this.formatJson(keyList, list);
import('@/vendor/Export2Excel').then(excel => {
excel.export_json_to_excel({
header,
data,
filename,
// autoWidth: this.autoWidth,
bookType: 'xlsx'
})
this.downloadLoading = false
})
},
formatJson(filterVal, jsonData, dataList = []) {
if (this.infotype == '任务') {
jsonData.forEach(v => {
const row = filterVal.map(j => {
let key = '';
return v[j];
})
dataList.push(row);
if (v.children && v.children.length) {
dataList = this.formatJson(filterVal, v.children, dataList);
}
})
return dataList;
} else if (this.infotype == '阶段计划') {
const bizFlowStateDict = {
0: '未发审',
1: '审核中',
2: '已通过',
3: '未通过',
4: '已取消'
}
jsonData.forEach(v => {
const row = filterVal.map(j => {
let key = '';
if(j == 'phaseStatus') {
return this.$refs.xmProjectPhaseMng.formateOption('xmPhaseStatus', v.phaseStatus);
} else if(j == 'bizFlowState') {
return `${bizFlowStateDict[parseInt(v[j]) || 0]}`;
} else {
return v[j];
}
})
dataList.push(row);
if (v.children && v.children.length) {
dataList = this.formatJson(filterVal, v.children, dataList);
}
})
return dataList;
} else if (this.infotype == '故事监控') {
jsonData.forEach(v => {
const row = filterVal.map(j => {
let key = '';
if(j == 'planStatus') {
key = 'xmMenuPlanStatus';
} else if(j == 'onlineStatus') {
return parseInt(v[j]) ? '已上线' : '未上线';
} else {
return v[j];
}
const options = this.$refs.xmMenuWithPlan.options;
if(options[key]==undefined || options[key]==null || options[key].length==0 ){
return v[j];
}
var rowData=options[key].filter(i=>i.optionValue==v[j])
if(rowData.length>0){
return rowData[0].optionName
}else{
return v[j];
}
});
dataList.push(row);
if (v.children && v.children.length) {
dataList = this.formatJson(filterVal, v.children, dataList);
}
})
return dataList;
}
},
getDateString(dateStr){
if(dateStr==null || dateStr=="" || dateStr==undefined){
return ""
}else{
return dateStr.substr(0,10);
}
},
goBack(){
this.$router.back()
}
},//end methods
components: {
xmTaskMng,
xmProjectPhaseMng,
xmGroupMng,
xmExchange,
xmQuestion,
xmFileMng,
xmDetail,
xmProjectKpi,
xmRecord,
xmCost,
xmBudget,
xmContract,
xmEnvList,
xmMenuMng,
xmMenuWithPlan,
xmProjectStateMng,
xmTestCaseExecMng,
xmProjectGroupSelect,
XmIterationForProjectComplex,
XmProductOverviewComplex,
XmProductForProjectComplex,
XmProjectForLink,
//
},
mounted() {
this.$nextTick(() => {
});
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.menus{
.el-menu-item{
padding-left: 0px !important;
}
}
/* 超过宽度则用...代替 */
.truncate{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>

61
src/views/xm/core/xmProduct/XmProductInfoRoute.vue

@ -0,0 +1,61 @@
<template>
<section>
<xm-product-info v-if="xmProduct" :xm-product="xmProduct" :visible="showInfo"></xm-product-info>
</section>
</template>
<script>
import util from '@/common/js/util';//
import { mapGetters } from 'vuex';
import XmProductInfo from './XmProductInfo'
export default {
computed: {
...mapGetters([
'userInfo','roles'
]),
},
watch:{
},
data() {
return {
xmProduct:null,
showInfo:false,
}
},//end data
methods: {
},//end methods
components: {
XmProductInfo,
//
},
activated(){
if(this.$route.params && this.$route.params.id){
this.xmProduct=this.$route.params
this.showInfo=true;
localStorage.setItem('xm-product-info-route',JSON.stringify(this.xmProduct));
}else{
this.xmProduct=JSON.parse(localStorage.getItem("xm-product-info-route"))
this.showInfo=true;
}
},
mounted() {
if(this.$route.params && this.$route.params.id){
this.xmProduct=this.$route.params
this.showInfo=true;
localStorage.setItem('xm-product-info-route',JSON.stringify(this.xmProduct));
}else{
this.xmProduct=JSON.parse(localStorage.getItem("xm-product-info-route"))
this.showInfo=true;
}
}
}
</script>
<style scoped>
</style>

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

@ -8,6 +8,7 @@
</el-select>
<el-input v-if="filters.queryScope=='productId'" style="width:20%;" v-model="filters.id" placeholder="输入产品编号" @keyup.enter.native="searchXmProducts">
</el-input>
<el-date-picker v-show="!selProject&&filters.queryScope!='productId'"
v-model="dateRanger"
type="daterange"
@ -27,11 +28,12 @@
<el-button v-loading="load.list" :disabled="load.list==true" v-on:click="searchXmProducts" icon="el-icon-search"></el-button>
</template>
</el-input>
<el-button type="primary" @click="showAdd" icon="el-icon-plus">产品</el-button>
<el-button v-if="xmIteration" icon="el-icon-plus" @click="productSelectVisible=true">将更多产品加入迭代<strong>{{xmIteration.iterationName}}</strong></el-button>
<el-button type="primary" @click="showAdd" icon="el-icon-plus" v-if="!xmIteration">产品</el-button>
<el-popover
placement="top-start"
title=""
width="400"
width="500"
trigger="click" >
<el-divider content-position="left"><strong>查询条件</strong></el-divider>
<el-row>
@ -104,6 +106,42 @@
<el-button slot="reference" icon="el-icon-more" circle></el-button>
</el-popover>
</el-row>
<el-row class="page-main page-height-80">
<!--列表 XmProject xm_project-->
<el-row v-show="showType" v-loading="load.list">
<el-col v-cloak v-for="(p,i) in xmProducts" :key="i" :xl="4" :lg="6" :md="8" :sm="12">
<el-card @click.native="intoInfo(p,i)" class="project-card" shadow="always">
<div class="project-name" title="这是产品名称">{{p.productName}}</div>
<div class="project-id eui-text-truncate">{{p.code}}</div>
<div class="project-info">
<div class="info-item">
<span class="item-total">{{p.totalBugCnt==null?0:p.totalBugCnt}}</span>
<span class="item-type">缺陷</span>
</div>
<div class="info-item">
<span class="item-total">{{p.totalFileCnt==null?0:p.totalFileCnt}}</span>
<span class="item-type">文档</span>
</div>
<div class="info-task">
<span>
<span class="item-total finish-task">{{p.totalCompleteTaskCnt==null?0:p.totalCompleteTaskCnt}}</span>
<span style="margin: 0 .25rem !important;">/</span>
<span class="item-type total-task">{{p.totalTaskCnt==null?0:p.totalTaskCnt}}</span>
</span>
<span class="item-type">任务完成</span>
</div>
</div>
<div class="project-rate">
<el-progress :percentage="(p.totalProgress==null?0:p.totalProgress)"></el-progress>
</div>
<div class="project-footer">
<div class="project-type">{{p.xmType}}</div>
<!--<div class="project-period">{{p.startTime.substr(0,10)}} ~{{p.endTime.substr(0,10)}}</div>-->
</div>
</el-card>
</el-col>
</el-row>
</el-row>
<el-row class="padding-top">
<!--列表 XmProduct 产品表-->
<el-table ref="table" :height="tableHeight" :data="xmProducts" @sort-change="sortChange" highlight-current-row v-loading="load.list" border @selection-change="selsChange" @row-click="rowClick" style="width: 100%;">
@ -273,6 +311,7 @@ import XmProductSelect from './XmProductSelect.vue';
pickerOptions: util.pickerOptions('datarange'),
projectVisible:false,
productSelectVisible:false,
showType:true,
/**begin 自定义属性请在下面加 请加备注**/
/**end 自定义属性请在上面加 请加备注**/
@ -411,6 +450,13 @@ import XmProductSelect from './XmProductSelect.vue';
this.editFormVisible=false;
this.getXmProducts()
},
//info
intoInfo(row) {
this.editForm = row;
this.$router.push({ name:'XmProductInfoRoute', params: row })
//this.showInfo = true;
},
//xmProduct
selsChange: function (sels) {
this.sels = sels;
@ -504,6 +550,9 @@ import XmProductSelect from './XmProductSelect.vue';
},
onProjectSelected(projects){
},
onXmIterationSelect(){
},
/**end 自定义函数请在上面加**/
onXmProductSelect:function(row){
@ -547,7 +596,7 @@ import XmProductSelect from './XmProductSelect.vue';
UsersSelect,
XmProjectList,
XmIterationSelect,
XmProductSelect,
XmProductSelect,
//
},
mounted() {
@ -575,3 +624,106 @@ XmProductSelect,
float: right;
}
</style>
<style scoped>
.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;
}
@media only screen and (max-height: 2400px) {
.project-box{
max-height: 1600x;
overflow-y: auto;
}
}
@media only screen and (max-height: 1200px) {
.project-box{
max-height: 800px;
overflow-y: auto;
}
}
@media only screen and (max-height: 980px) {
.project-box{
max-height: 600px;
overflow-y: auto;
}
}
@media only screen and (max-height: 640px) {
.project-box{
max-height: 300px;
overflow-y: auto;
}
}
</style>

1008
src/views/xm/core/xmProduct/XmProductOverview.vue
File diff suppressed because it is too large
View File

130
src/views/xm/core/xmProduct/XmProductOverviewComplex.vue

@ -0,0 +1,130 @@
<template>
<section class="page-container page-height-90 padding-left padding-right">
<el-menu mode="horizontal" default-active="overiew" @select="onMenuToolBarSelect">
<el-menu-item index="overiew">
<span slot="title">项目概览</span>
</el-menu-item>
<el-menu-item index="detail">
<span slot="title">项目详情</span>
</el-menu-item>
<el-submenu index="project-change">
<template slot="title">
<span slot="title">项目变更</span>
</template>
<el-menu-item index="project-change-base-info">
<span slot="title">基础信息修改</span>
</el-menu-item>
<el-menu-item index="project-change-start">
<span slot="title">立项申请</span>
</el-menu-item>
<el-menu-item index="project-change-budget">
<span slot="title">预算+-</span>
</el-menu-item>
<el-menu-item index="project-change-cost">
<span slot="title">成本+-</span>
</el-menu-item>
<el-menu-item index="project-change-collection">
<span slot="title">收款</span>
</el-menu-item>
<el-menu-item index="project-change-conclusion">
<span slot="title">结项申请</span>
</el-menu-item>
<el-menu-item index="project-change-suspend">
<span slot="title">暂停申请</span>
</el-menu-item>
<el-menu-item index="project-change-activation">
<span slot="title">激活申请</span>
</el-menu-item>
<el-menu-item index="project-change-to-after-sales">
<span slot="title">转售后申请</span>
</el-menu-item>
<el-menu-item index="project-change-new-pm">
<span slot="title">项目经理变更申请</span>
</el-menu-item>
<el-menu-item index="project-change-new-leader">
<span slot="title">组长变更申请</span>
</el-menu-item>
</el-submenu>
<el-submenu index="menu-change">
<template slot="title">
<span slot="title">需求变更</span>
</template>
<el-menu-item index="menu-change-review">
<span slot="title">需求评审</span>
</el-menu-item>
<el-menu-item index="menu-change-border-review">
<span slot="title">需求边界异动</span>
</el-menu-item>
</el-submenu>
<el-submenu index="iteration-change">
<template slot="title">
<span slot="title">迭代变更</span>
</template>
<el-menu-item index="iteration-change-review">
<span slot="title">迭代计划评审</span>
</el-menu-item>
<el-menu-item index="iteration-change-border-review">
<span slot="title">迭代上线申请</span>
</el-menu-item>
</el-submenu>
<el-submenu index="phase-change">
<template slot="title">
<span slot="title">阶段计划变更</span>
</template>
<el-menu-item index="phase-change-review">
<span slot="title">计划评审</span>
</el-menu-item>
<el-menu-item index="phase-change-border-review">
<span slot="title">预算变更</span>
</el-menu-item>
</el-submenu>
</el-menu>
<xm-product-overview v-if="showPanelName=='overiew'" :xm-product="xmProduct"></xm-product-overview>
<xm-product-edit v-if="showPanelName=='detail'" :xm-product="xmProduct"></xm-product-edit>
</section>
</template>
<script>
import util from "@/common/js/util"; //
//import Sticky from "@/components/Sticky"; // header
import { mapGetters } from "vuex";
import { listXmProjectState } from '@/api/xm/core/xmProductState';
import XmProductOverview from './XmProductOverview.vue';
import XmProductEdit from './XmProductEdit.vue';
export default {
components: { XmProductOverview, XmProductEdit },
computed: {
...mapGetters(["userInfo"]),
},
props:['selProject'],
watch:{
},
data() {
return {
showPanelName:'overiew'
};
},
methods:{
onMenuToolBarSelect(menuIndex){
this.showPanelName=menuIndex;
}
},
mounted() {
this.$nextTick(() => {
});
},
};
</script>
<style scoped lang="scss">
</style>

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

@ -6,6 +6,10 @@
<el-button @click="searchXmProjects" icon="el-icon-search"></el-button>
</template>
</el-input>
<el-button icon="el-icon-plus" @click="xmProjectListVisible=true" v-if="!xmIteration">
加入更多项目到产品中
</el-button>
</el-row>
<el-row class="page-main page-height-90">
<el-table ref="table" :height="tableHeight" stripe :data="xmProjects" highlight-current-row v-loading="load.list" style="width: 100%;">
@ -15,9 +19,8 @@
<el-table-column label="操作" width="245" fixed="right">
<template slot-scope="scope">
<el-button-group>
<el-button size="mini" type="primary" @click.stop="selectProject(scope.row)" >选中</el-button>
<el-button v-if="!xmIteration" size="mini" type="primary" @click.stop="doDelXmProductProjectLink(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>
@ -25,6 +28,10 @@
</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-drawer title="选择项目" :visible.sync="xmProjectListVisible" size="60%" append-to-body>
<xm-project-list @project-confirm="onXmProjectSelect"></xm-project-list>
</el-drawer>
</section>
</template>
@ -37,11 +44,13 @@
//import { listOption } from '@/api/mdp/meta/itemOption';//
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';
export default {
props:['xmProduct'],
props:['xmProduct','xmIteration'],
computed: {
...mapGetters([
'userInfo','roles'
@ -50,6 +59,9 @@
watch:{
xmProduct:function(){
this.getXmProjects();
},
xmIteration:function(){
this.getXmProjects();
}
},
data() {
@ -82,7 +94,7 @@
editForm: {
id:'',code:'',name:'',xmType:'',startTime:'',endTime:'',urgent:'',priority:'',description:'',createUserid:'',createUsername:'',createTime:'',assess:'',assessRemarks:'',status:'',branchId:'',planTotalCost:'',bizProcInstId:'',bizFlowState:'',planNouserAt:'',planInnerUserAt:'',planOutUserAt:'',locked:'',baseTime:'',baseRemark:'',baselineId:'',planWorkload:'',totalReceivables:'',budgetMarginRate:'',contractAmt:'',planInnerUserPrice:'',budgetOutUserPrice:'',planOutUserCnt:'',planInnerUserCnt:'',planWorkingHours:''
},
xmProjectListVisible:false,
/**end 自定义属性请在上面加 请加备注**/
}
@ -125,6 +137,10 @@
if(this.xmProduct){
params.productId=this.xmProduct.id
}
if(this.xmIteration){
params.iterationId=this.xmIteration.id
}
if(this.filters.key){
params.key='%'+this.filters.key+'%'
}
@ -153,11 +169,46 @@
selectProject:function(row){
this.editForm=row
this.$emit('project-confirm',this.editForm);
},
/**end 自定义函数请在上面加**/
onXmProjectSelect:function(row){
var xmProject=row;
var xmProduct=this.xmProduct;
this.$confirm('确认将项目【'+xmProject.name+'】加入产品【'+xmProduct.productName+'】吗?', '提示', {
type: 'warning'
}).then(()=>{
addXmProductProjectLink({projectId:xmProject.id,productId:xmProduct.id}).then(res=>{
var tips =res.data.tips;
if(tips.isOk){
this.getXmProjects();
}
this.$message({showClose: true, message: tips.msg, type: tips.isOk?'success':'error'});
})
})
},
doDelXmProductProjectLink(row){
var xmProduct=this.xmProduct;
var selProject=row;
this.$confirm('确认将项目【'+selProject.projectName+'】从产品【'+xmProduct.productName+'】移出吗?移出后,项目试图中将看不到该产品信息', '提示', {
type: 'warning'
}).then(()=>{
var params={productId:xmProduct.id,projectId:selProject.id}
delXmProductProjectLink(params).then(res=>{
var tips = res.data.tips;
if(tips.isOk){
this.getXmProjects();
this.$message({showClose: true, message: "移出成功", type: 'success' });
}
});
})
}
/**end 自定义函数请在上面加**/
},//end methods
components: {
XmProjectList
//
},

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

@ -142,8 +142,8 @@
</el-menu>
<xm-project-overview-complex v-if="infotype=='项目概览'" :sel-project="selProject"></xm-project-overview-complex>
<xm-iteration-complex v-if="infotype=='迭代'" ref="xmIterationMng" :sel-project="selProject" ></xm-iteration-complex>
<xm-product-complex v-if="infotype=='产品'" ref="xmProductComplex" :sel-project="selProject" ></xm-product-complex>
<xm-iteration-for-project-complex v-if="infotype=='迭代'" ref="xmIterationMng" :sel-project="selProject"></xm-iteration-for-project-complex>
<xm-product-for-project-complex v-if="infotype=='产品'" ref="xmProductComplex" :sel-project="selProject"></xm-product-for-project-complex>
<xm-menu-mng v-if="infotype=='用户故事'" :sel-project="selProject"></xm-menu-mng>
<xm-task-mng v-if="infotype=='任务'" ref="xmTaskMng" :sel-project="selProject" ></xm-task-mng>
<xm-question v-if="infotype=='缺陷'" :qtype="'bug'" :sel-project='selProject' ref="xmQuestion"></xm-question>
@ -194,9 +194,9 @@
import xmMenuWithPlan from '../xmMenu/XmMenuWithPlan';
import xmProjectStateMng from '../xmProjectState/XmProjectStateMng';
import xmTestCaseExecMng from '../xmTestCaseExec/XmTestCaseExecMng';
import XmIterationComplex from '../xmIteration/XmIterationComplex.vue';
import XmIterationForProjectComplex from '../xmIteration/XmIterationForProjectComplex.vue';
import XmProjectOverviewComplex from './XmProjectOverviewComplex.vue';
import XmProductComplex from '../xmProduct/XmProductComplex.vue';
import XmProductForProjectComplex from '../xmProduct/XmProductForProjectComplex.vue';
export default {
@ -416,9 +416,9 @@ import XmProductComplex from '../xmProduct/XmProductComplex.vue';
xmProjectStateMng,
xmTestCaseExecMng,
xmProjectGroupSelect,
XmIterationComplex,
XmIterationForProjectComplex,
XmProjectOverviewComplex,
XmProductComplex,
XmProductForProjectComplex,
//
},
mounted() {

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

@ -56,7 +56,7 @@
<el-button v-if=" isTaskCenter!='1' && isMy!='1'" @click="showAdd" icon="el-icon-plus">直接创建</el-button>
</el-col>
</el-row>
<el-button slot="reference" v-if=" isTaskCenter!='1' && isMy!='1'" type="primary" icon="el-icon-plus" circle></el-button>
<el-button slot="reference" v-if=" isTaskCenter!='1' && isMy!='1' && !xmProduct && !xmIteration" type="primary" icon="el-icon-plus" circle></el-button>
</el-popover>
<el-popover

Loading…
Cancel
Save