|
@@ -1,155 +1,205 @@
|
|
|
<template>
|
|
|
<div class="sos" style="background-color:#F2F3F6;min-height:calc(100vh - 80px);padding:0 10px 10px 10px">
|
|
|
<div class="stylus-head">
|
|
|
- <div class="stylus-title">
|
|
|
- <span style="font-size: 22px;letter-spacing: 1px;font-weight: 600;color: #333B4A;padding-left: 15px">需求</span>
|
|
|
- <div class="new-tab-open">
|
|
|
- <el-switch
|
|
|
- v-model="newTabOpen"
|
|
|
- active-text="新标签页跳转"
|
|
|
- @change="logHandle('switchJumpOpen')"
|
|
|
- />
|
|
|
- </div>
|
|
|
- <el-button type="primary" size="mini" @click="createDialogVisible = true">新建需求</el-button>
|
|
|
- </div>
|
|
|
- <el-divider style="color: #EEF0F5;" />
|
|
|
- <div class="Layout" style="padding-top: 5px">
|
|
|
- <div>
|
|
|
- <el-form :model="searchForm" class="Layout">
|
|
|
- <div class="Layout_flex_end" style="padding-left:15px">
|
|
|
- <div class="queryName">需求名称</div>
|
|
|
- <el-input v-model="requirementName" size="small" clearable style="width:72% !important;" placeholder="请搜索标题或ID或望岳ID" @change="getTableData()" />
|
|
|
- </div>
|
|
|
+ <mainTitle
|
|
|
+ title="需求"
|
|
|
+ btn-text="新建需求"
|
|
|
+ :tab-show="true"
|
|
|
+ @btn-handle="createDialogVisible = true"
|
|
|
+ @change-tab="changeTab"
|
|
|
+ />
|
|
|
+ <div v-if="nowTab === 'charts'" class="chartView">
|
|
|
+ <chartView
|
|
|
+ :data="chartData"
|
|
|
+ :type-option-list="typeOptionList"
|
|
|
+ :chart-search-data="searchForm"
|
|
|
+ @search="get_charts()"
|
|
|
+ @changeList="(code) => get_chartListDetial(code)"
|
|
|
+ >
|
|
|
+ <div slot="searchBox">
|
|
|
<div class="Layout">
|
|
|
- <div class="queryName marginLeft">需求状态</div>
|
|
|
- <el-select v-model="searchForm.statusList" size="small" multiple clearable filterable placeholder="请选择" @change="getTableData()">
|
|
|
- <el-option v-for="(item, index) in requiredStatus" :key="index" :label="item.msg" :value="item.code" />
|
|
|
- </el-select>
|
|
|
- </div>
|
|
|
- <div class="Layout">
|
|
|
- <div class="queryName marginLeft">需求方向</div>
|
|
|
- <el-cascader v-model="searchForm.rqmtOrntIds" size="small" collapse-tags :props="props" :options="demandDirection" placeholder="请选择" style="width: 72%" @change="getTableData()" />
|
|
|
+ <div class="Layout">
|
|
|
+ <div class="queryName">需求方向</div>
|
|
|
+ <el-cascader v-model="searchForm.rqmtOrntIds" size="small" collapse-tags :props="props" :options="demandDirection" placeholder="请选择" style="width: 72%" @change="get_charts()" />
|
|
|
+ </div>
|
|
|
+ <span class="screen" style="text-align:right" @click="showChartModal = true">更多筛选</span>
|
|
|
</div>
|
|
|
- </el-form>
|
|
|
- </div>
|
|
|
- <span class="screen" @click="showSelect">{{ goodName }}</span>
|
|
|
+ </div>
|
|
|
+ </chartView>
|
|
|
</div>
|
|
|
- <div v-show="DetailedScreening" class="stylus-more">
|
|
|
- <div>
|
|
|
- <el-form :model="searchForm" class="flex_start">
|
|
|
- <div class="Layout">
|
|
|
- <div class="queryName">所属项目</div>
|
|
|
- <el-select v-model="searchForm.belongingProject" size="small" clearable filterable placeholder="请选择">
|
|
|
- <el-option v-for="item in AttributionItems" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
- </el-select>
|
|
|
- </div>
|
|
|
- <div class="Layout">
|
|
|
- <div class="queryName marginLeft">PM</div>
|
|
|
- <search-people :value.sync="searchForm.pm" :clearable="true" :multiple="false" style="width:72% !important;" />
|
|
|
- </div>
|
|
|
- <div class="Layout">
|
|
|
- <div class="queryName marginLeft">需求类型</div>
|
|
|
- <el-select v-model="searchForm.type" size="small" clearable filterable placeholder="请选择">
|
|
|
- <el-option v-for="item in searchInfo.type" :key="item.code" :label="item.msg" :value="item.code" />
|
|
|
- </el-select>
|
|
|
- </div>
|
|
|
- </el-form>
|
|
|
- <el-form :model="searchForm" class="flex_start el-from-spacing">
|
|
|
- <div class="Layout">
|
|
|
- <div class="queryName">需求来源</div>
|
|
|
- <el-select v-model="searchForm.sourceTypeList" size="small" multiple clearable filterable placeholder="请选择">
|
|
|
- <el-option v-for="item in searchInfo.sourceType" :key="item.code" :label="item.msg" :value="item.code" />
|
|
|
- </el-select>
|
|
|
- </div>
|
|
|
- <div class="Layout">
|
|
|
- <div class="queryName marginLeft">优先级</div>
|
|
|
- <el-select v-model="searchForm.priorityList" size="small" multiple clearable filterable placeholder="请选择">
|
|
|
- <el-option v-for="item in searchInfo.priority" :key="item.code" :label="item.msg" :value="item.code" />
|
|
|
+ <div v-if="nowTab === 'list'" class="search_box">
|
|
|
+ <div class="Layout" style="padding: 5px 0 0 15px">
|
|
|
+ <div>
|
|
|
+ <el-form :model="searchForm" class="Layout">
|
|
|
+ <div class="Layout_flex_end item">
|
|
|
+ <div class="queryName">需求名称</div>
|
|
|
+ <el-input v-model="searchForm.name" size="small" clearable style="width:72% !important;" placeholder="请搜索标题或ID或望岳ID" @change="getTableData()" />
|
|
|
+ </div>
|
|
|
+ <div class="Layout item">
|
|
|
+ <div class="queryName">需求状态</div>
|
|
|
+ <el-select v-model="searchForm.statusList" size="small" multiple clearable filterable placeholder="请选择" @change="getTableData()">
|
|
|
+ <el-option v-for="(item, index) in requiredStatus" :key="index" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="Layout item">
|
|
|
+ <div class="queryName">需求方向</div>
|
|
|
+ <el-cascader v-model="searchForm.rqmtOrntIds" size="small" collapse-tags :props="props" :options="demandDirection" placeholder="请选择" style="width: 72%" @change="getTableData()" />
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ <span class="screen" @click="showSelect">{{ goodName }}</span>
|
|
|
+ </div>
|
|
|
+ <div v-show="DetailedScreening" class="stylus-more">
|
|
|
+ <div>
|
|
|
+ <el-form :model="searchForm" class="flex_start">
|
|
|
+ <div class="Layout item">
|
|
|
+ <div class="queryName">所属项目</div>
|
|
|
+ <el-select v-model="searchForm.belongingProject" size="small" clearable filterable placeholder="请选择">
|
|
|
+ <el-option v-for="item in AttributionItems" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="Layout item">
|
|
|
+ <div class="queryName">PM</div>
|
|
|
+ <!-- <search-people :value.sync="searchForm.pm" :clearable="true" :multiple="false" style="width:72% !important;" /> -->
|
|
|
+ <el-select
|
|
|
+ v-model="searchForm.pm"
|
|
|
+ clearable
|
|
|
+ filterable
|
|
|
+ remote
|
|
|
+ placeholder="请输入姓名或邮箱前缀"
|
|
|
+ :remote-method="remoteMethod"
|
|
|
+ :loading="loading"
|
|
|
+ size="small"
|
|
|
+ >
|
|
|
+ <el-option v-for="item in options" :key="item.idap" :label="item.name" :value="item.idap">
|
|
|
+ <div class="flex_start">
|
|
|
+ <div class="deptName">{{ item.deptName }}</div>
|
|
|
+ <div style="min-width:80px">{{ item.name }}</div>
|
|
|
+ <div class="deptName">{{ item.idap }}</div>
|
|
|
+ </div>
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="Layout item">
|
|
|
+ <div class="queryName">需求类型</div>
|
|
|
+ <el-select v-model="searchForm.type" size="small" clearable filterable placeholder="请选择">
|
|
|
+ <el-option v-for="item in searchInfo.type" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ <el-form :model="searchForm" class="flex_start el-from-spacing">
|
|
|
+ <div class="Layout item">
|
|
|
+ <div class="queryName">需求来源</div>
|
|
|
+ <el-select v-model="searchForm.sourceTypeList" size="small" multiple clearable filterable placeholder="请选择">
|
|
|
+ <el-option v-for="item in searchInfo.sourceType" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="Layout item">
|
|
|
+ <div class="queryName">优先级</div>
|
|
|
+ <el-select v-model="searchForm.priorityList" size="small" multiple clearable filterable placeholder="请选择">
|
|
|
+ <el-option v-for="item in searchInfo.priority" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="Layout item">
|
|
|
+ <div class="queryName">需求提出人</div>
|
|
|
+ <!-- <search-people :value.sync="searchForm.rqmtProposer" :clearable="true" :multiple="false" style="width:72% !important;" /> -->
|
|
|
+ <el-select
|
|
|
+ v-model="searchForm.rqmtProposer"
|
|
|
+ clearable
|
|
|
+ filterable
|
|
|
+ remote
|
|
|
+ placeholder="请输入姓名或邮箱前缀"
|
|
|
+ :remote-method="remoteMethod"
|
|
|
+ :loading="loading"
|
|
|
+ size="small"
|
|
|
+ >
|
|
|
+ <el-option v-for="item in options" :key="item.idap" :label="item.name" :value="item.idap">
|
|
|
+ <div class="flex_start">
|
|
|
+ <div class="deptName">{{ item.deptName }}</div>
|
|
|
+ <div style="min-width:80px">{{ item.name }}</div>
|
|
|
+ <div class="deptName">{{ item.idap }}</div>
|
|
|
+ </div>
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ <el-form :model="searchForm" class="flex_start el-from-spacing">
|
|
|
+ <div class="Layout item">
|
|
|
+ <div class="queryName">来自望岳</div>
|
|
|
+ <el-select v-model="searchForm.isFromDpm" size="small" clearable filterable placeholder="请选择">
|
|
|
+ <el-option v-for="item in isFromDpmList" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div class="Layout item">
|
|
|
+ <div class="queryName">创建时间</div>
|
|
|
+ <el-date-picker
|
|
|
+ v-model="searchForm.date"
|
|
|
+ type="daterange"
|
|
|
+ align="right"
|
|
|
+ unlink-panels
|
|
|
+ range-separator="至"
|
|
|
+ start-placeholder="开始日期"
|
|
|
+ end-placeholder="结束日期"
|
|
|
+ size="small"
|
|
|
+ style="min-width: 476px"
|
|
|
+ value-format="yyyy-MM-dd HH:mm:ss"
|
|
|
+ :default-time="['00:00:00','23:59:59']"
|
|
|
+ :picker-options="pickerOptions"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ <div v-if="DemandStatus === true" style="color:#409EFF; cursor: pointer; margin-top: 15px;" @click="DemandSta"><i class="el-icon-circle-plus-outline" /> 添加需求状态停留时长条件</div>
|
|
|
+ <el-divider v-if="DemandStatus === false"> 且 </el-divider>
|
|
|
+ <div v-if="DemandStatus === false" style=" margin-top: 15px;">
|
|
|
+ <div class="DemandStatus">
|
|
|
+ <i style="color:#409EFF; cursor: pointer; margin-right: 5px;" class="el-icon-remove-outline" @click="DemandSta" />
|
|
|
+ <span> 需求状态包含:</span>
|
|
|
+ </div>
|
|
|
+ <el-checkbox-group v-model="searchForm.containStatus" class="allCheckbox">
|
|
|
+ <el-checkbox v-for="item in requiredStatus" :key="item.value" :value="item.value">{{ item.label }}</el-checkbox>
|
|
|
+ </el-checkbox-group>
|
|
|
+ <div class="DemandStatus">状态停留时长:</div>
|
|
|
+ <el-select v-model="searchForm.comparisonOperator" size="small" style="width: 80px; margin: 20px 20px 0 79px;" clearable filterable placeholder="请选择">
|
|
|
+ <el-option v-for="item in formula" :key="item.code" :label="item.msg" :value="item.msg" />
|
|
|
</el-select>
|
|
|
- </div>
|
|
|
- <div class="Layout">
|
|
|
- <div class="queryName marginLeft">需求提出人</div>
|
|
|
- <search-people :value.sync="searchForm.rqmtProposer" :clearable="true" :multiple="false" style="width:72% !important;" />
|
|
|
- </div>
|
|
|
- </el-form>
|
|
|
- <el-form :model="searchForm" class="flex_start el-from-spacing">
|
|
|
- <div class="Layout">
|
|
|
- <div class="queryName">来自望岳</div>
|
|
|
- <el-select v-model="searchForm.isFromDpm" size="small" clearable filterable placeholder="请选择">
|
|
|
- <el-option v-for="item in isFromDpmList" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
+ <el-select v-model="searchForm.days" size="small" style="width: 80px;" clearable filterable placeholder="请选择">
|
|
|
+ <el-option v-for="item in getArrayList()" :key="item.code" :label="item.msg" :value="item.code" />
|
|
|
</el-select>
|
|
|
</div>
|
|
|
- <div class="Layout">
|
|
|
- <div class="queryName" style="margin-left: 2%;">创建时间</div>
|
|
|
- <el-date-picker
|
|
|
- v-model="searchForm.date"
|
|
|
- type="daterange"
|
|
|
- align="right"
|
|
|
- unlink-panels
|
|
|
- range-separator="至"
|
|
|
- start-placeholder="开始日期"
|
|
|
- end-placeholder="结束日期"
|
|
|
- size="small"
|
|
|
- value-format="yyyy-MM-dd HH:mm:ss"
|
|
|
- :default-time="['00:00:00','23:59:59']"
|
|
|
- :picker-options="pickerOptions"
|
|
|
- />
|
|
|
+
|
|
|
+ <div align="right">
|
|
|
+ <el-button type="text" @click="showSaveSearch = true">保存筛选项</el-button>
|
|
|
+ <el-button type="primary" size="mini" @click="getTableData">筛 选</el-button>
|
|
|
+ <el-button size="mini" @click="reset">重 置</el-button>
|
|
|
</div>
|
|
|
- </el-form>
|
|
|
- <div v-if="DemandStatus === true" style="color:#409EFF; cursor: pointer; margin-top: 15px;" @click="DemandSta"><i class="el-icon-circle-plus-outline" /> 添加需求状态停留时长条件</div>
|
|
|
- <el-divider v-if="DemandStatus === false"> 且 </el-divider>
|
|
|
- <div v-if="DemandStatus === false" style=" margin-top: 15px;">
|
|
|
- <div class="DemandStatus">
|
|
|
- <i style="color:#409EFF; cursor: pointer; margin-right: 5px;" class="el-icon-remove-outline" @click="DemandSta" />
|
|
|
- <span> 需求状态包含:</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-if="filterList.length && filterList.length > 0" class="filter">
|
|
|
+ <div class="filterWrap">
|
|
|
+ <div class="title">我的过滤器:</div>
|
|
|
+ <div class="itemBox">
|
|
|
+ <el-tag v-for="item in filterList" :key="item.id" class="item" @click="getFilterItem(item.id)">{{ item.name }}</el-tag>
|
|
|
</div>
|
|
|
- <el-checkbox-group v-model="searchForm.containStatus" class="allCheckbox">
|
|
|
- <el-checkbox v-for="item in requiredStatus" :key="item.code" :label="item.code">{{ item.msg }}</el-checkbox>
|
|
|
- </el-checkbox-group>
|
|
|
- <div class="DemandStatus">状态停留时长:</div>
|
|
|
- <el-select v-model="searchForm.comparisonOperator" size="small" style="width: 80px; margin: 20px 20px 0 79px;" clearable filterable placeholder="请选择">
|
|
|
- <el-option v-for="item in formula" :key="item.code" :label="item.msg" :value="item.msg" />
|
|
|
- </el-select>
|
|
|
- <el-select v-model="searchForm.days" size="small" style="width: 80px;" clearable filterable placeholder="请选择">
|
|
|
- <el-option v-for="item in getArrayList()" :key="item.code" :label="item.msg" :value="item.code" />
|
|
|
- </el-select>
|
|
|
</div>
|
|
|
-
|
|
|
- <div align="right">
|
|
|
- <el-button type="text" @click="showSaveSearch = true">保存筛选项</el-button>
|
|
|
- <el-button type="primary" size="mini" @click="getTableData">筛 选</el-button>
|
|
|
- <el-button size="mini" @click="reset">重 置</el-button>
|
|
|
+ <div class="btn">
|
|
|
+ <span @click.stop="showEditSearch = true">管理过滤器</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <el-row v-if="filterList.length && filterList.length>0" type="flex" justify="space-between" class="filter">
|
|
|
- <el-col :span="2">
|
|
|
- <span>我的过滤器:</span>
|
|
|
- </el-col>
|
|
|
- <el-col :span="20" class="mine-filter">
|
|
|
- <span v-for="item in filterList" :key="item.id" class="filter-item" @click="getFilterItem(item.id)">
|
|
|
- <el-tooltip class="item" effect="dark" :content="item.name" placement="bottom">
|
|
|
- <span>{{ item.name }}</span>
|
|
|
- </el-tooltip>
|
|
|
- </span>
|
|
|
- </el-col>
|
|
|
- <el-col :span="2" align="end">
|
|
|
- <span @click.stop="showEditSearch = true">管理过滤器</span>
|
|
|
- </el-col>
|
|
|
- </el-row>
|
|
|
</div>
|
|
|
<div class="stylus-content">
|
|
|
+ <div v-if="nowTab === 'charts'" class="subtitle">{{ tableTitle }}</div>
|
|
|
<el-table
|
|
|
v-loading="loading"
|
|
|
:data="tableData"
|
|
|
style="width: 100%"
|
|
|
highlight-current-row
|
|
|
- :header-cell-style="{ 'color':'rgba(74,74,74,1)','font-size':'14px','font-weight':'500' }"
|
|
|
+ :header-cell-style="{ 'background': nowTab === 'charts' ? '#F7F7F7' : '#fff', 'color':'rgba(74,74,74,1)','font-size':'14px','font-weight':'500' }"
|
|
|
:cell-style="{ 'font-size':'14px','color':'rgba(102,102,102,1)' }"
|
|
|
size="small"
|
|
|
show-overflow-tooltip="true"
|
|
|
>
|
|
|
- <el-table-column label="优先级" fixed min-width="90" sortable align="left">
|
|
|
+ <el-table-column label="优先级" prop="priority" fixed min-width="90" sortable align="left">
|
|
|
<template v-slot="scope">
|
|
|
<div class="div_priority" :style="{background: priorityColors[scope.row.priority % priorityColors.length]}">{{ 'P'+scope.row.priority }}</div>
|
|
|
</template>
|
|
@@ -169,7 +219,25 @@
|
|
|
<span class="stylus-hover" @click="getToRequirementDetails(scope.row.id)">{{ scope.row.name }}</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="状态" prop="statusName" min-width="150" align="center" />
|
|
|
+ <el-table-column label="状态" prop="statusName" width="150" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-select
|
|
|
+ v-if="nowTab === 'charts'"
|
|
|
+ v-model="scope.row.status"
|
|
|
+ :class="{
|
|
|
+ 'status0':scope.row.status===0,
|
|
|
+ 'status1':scope.row.status > 0 && scope.row.status <100,
|
|
|
+ 'status2':scope.row.status===100
|
|
|
+ }"
|
|
|
+ :size="size"
|
|
|
+ placeholder=""
|
|
|
+ @change="(e) => statusChange(e, scope.row.id)"
|
|
|
+ >
|
|
|
+ <el-option v-for="o in scope.row.availableStatusList" :key="o.code" :label="o.name" :value="o.code" />
|
|
|
+ </el-select>
|
|
|
+ <span v-else>{{ scope.row.statusName }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
<el-table-column prop="sourceTypeName" label="需求来源" min-width="100" show-overflow-tooltip align="center" />
|
|
|
<el-table-column label="PM" min-width="100" show-overflow-tooltip align="center">
|
|
|
<template v-if="scope.row.pmMemberInfoResponse" slot-scope="scope">
|
|
@@ -220,10 +288,28 @@
|
|
|
<normal-dialog :show-footer="false" :show-dialog="showEditSearch" :title="'管理过滤器'" :width="'65%'" @cancel="showEditSearch=false">
|
|
|
<filter-list :show-filter="showEditSearch" @deleteFilter="deleteFilter" />
|
|
|
</normal-dialog>
|
|
|
+ <filterModal
|
|
|
+ :show-dialog="showChartModal"
|
|
|
+ title="筛选项"
|
|
|
+ @reset="reset"
|
|
|
+ @cancel="showChartModal = false"
|
|
|
+ @confirm="filterModalConfirm"
|
|
|
+ >
|
|
|
+ <div>
|
|
|
+ <chartSearchForm
|
|
|
+ :data="chartSearchFormRenderData"
|
|
|
+ :loading="loading"
|
|
|
+ :styles="{ marginBottom: '15px', width: '380px' }"
|
|
|
+ @change="chartSearchFormChange"
|
|
|
+ @getOption="(key, q, utilName) => remoteMethod(q)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </filterModal>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
+const _ = require('lodash')
|
|
|
import { EncryptId } from '@/utils/crypto-js.js'
|
|
|
import { mapGetters } from 'vuex'
|
|
|
import {
|
|
@@ -234,13 +320,21 @@ import {
|
|
|
settingQueryBizRqmtOrntList,
|
|
|
filterCreateFilter,
|
|
|
filtergetFilterList,
|
|
|
- filterGetFilter
|
|
|
+ filterGetFilter,
|
|
|
+ getPerson,
|
|
|
+ getChartListData,
|
|
|
+ getChartData,
|
|
|
+ updateStatus
|
|
|
} from '@/api/requirement.js'
|
|
|
import { deepClone } from '@/utils/global'
|
|
|
import RequirementCreate from './create'
|
|
|
+import mainTitle from '@/components/mainTitle'
|
|
|
+import chartView from '@/components/chartView'
|
|
|
+import filterModal from '@/components/filterModal'
|
|
|
+import chartSearchFormData from '../renderData/chartSearchForm'
|
|
|
+import chartSearchForm from '@/components/searchHeader/searchForm'
|
|
|
import filterList from '@/views/projectManage/components/filterList'
|
|
|
import extraUrgent from '@/assets/extraUrgent.png'
|
|
|
-import searchPeople from '@/components/select/searchPeople'
|
|
|
import normalDialog from '@/components/dialog/normalDialog'
|
|
|
import '@/views/projectManage/publicCss/index.css'
|
|
|
import '@/styles/PublicStyle/index.scss'
|
|
@@ -248,12 +342,16 @@ import '@/styles/PublicStyle/index.scss'
|
|
|
export default {
|
|
|
components: {
|
|
|
RequirementCreate,
|
|
|
- searchPeople,
|
|
|
normalDialog,
|
|
|
- filterList
|
|
|
+ filterList,
|
|
|
+ mainTitle,
|
|
|
+ chartView,
|
|
|
+ filterModal,
|
|
|
+ chartSearchForm
|
|
|
},
|
|
|
data() {
|
|
|
return {
|
|
|
+ size: 'small',
|
|
|
pickerOptions: {
|
|
|
shortcuts: [{
|
|
|
text: '最近一周',
|
|
@@ -281,10 +379,10 @@ export default {
|
|
|
}
|
|
|
}]
|
|
|
},
|
|
|
- newTabOpen: true, // 是否新的tab页打开
|
|
|
+ // newTabOpen: true, // 是否新的tab页打开
|
|
|
DemandStatus: true, // 筛选需求时长
|
|
|
extraUrgent: extraUrgent,
|
|
|
- isFromDpmList: [{ id: true, name: '是' }, { id: false, name: '否' }],
|
|
|
+ isFromDpmList: [{ value: true, label: '是' }, { value: false, label: '否' }],
|
|
|
priorityColors: ['#F56C6C', '#FF8952', '#F5E300', '#7ED321', '#61D3B8', '#69B3FF', '#BDBDBD'],
|
|
|
formula: [{ code: 0, msg: '>=' }, { code: 1, msg: '<=' }, { code: 2, msg: '>' }, { code: 3, msg: '<' }],
|
|
|
// currentRow: null,
|
|
@@ -305,7 +403,6 @@ export default {
|
|
|
bizType: [],
|
|
|
priority: []
|
|
|
},
|
|
|
- requirementName: '',
|
|
|
goodName: '更多筛选',
|
|
|
DetailedScreening: false,
|
|
|
searchFormRules: { name: [
|
|
@@ -318,6 +415,7 @@ export default {
|
|
|
requiredStatus: [], // 需求状态option
|
|
|
demandDirection: [], // 需求方向option
|
|
|
searchForm: {
|
|
|
+ viewType: '0',
|
|
|
containStatus: [] // 包含
|
|
|
}, // 查询字段
|
|
|
pageSize: 15,
|
|
@@ -326,7 +424,20 @@ export default {
|
|
|
tableData: [], // 需求tableList
|
|
|
createDialogVisible: false,
|
|
|
total: 0,
|
|
|
- data: ''
|
|
|
+ data: '',
|
|
|
+ options: [],
|
|
|
+ nowTab: 'list',
|
|
|
+ chartData: {},
|
|
|
+ typeOptionList: [
|
|
|
+ { value: '0', label: '需求状态' },
|
|
|
+ { value: '1', label: '需求等级' },
|
|
|
+ { value: '2', label: '需求类型' },
|
|
|
+ { value: '3', label: 'pm' },
|
|
|
+ { value: '4', label: '跟版客户端' }
|
|
|
+ ],
|
|
|
+ showChartModal: false,
|
|
|
+ tableTitle: '',
|
|
|
+ chartSearchFormRenderData: _.cloneDeep(chartSearchFormData)
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
@@ -346,25 +457,49 @@ export default {
|
|
|
created() {
|
|
|
this.$store.state.data.status = true
|
|
|
},
|
|
|
+ mounted() {
|
|
|
+ this.updateChartSlectOption('isFromDpm', this.isFromDpmList)
|
|
|
+ },
|
|
|
destroyed() {
|
|
|
this.$store.state.data.status = false
|
|
|
},
|
|
|
methods: {
|
|
|
+ // 修改状态
|
|
|
+ async statusChange(e, id) {
|
|
|
+ console.log(e)
|
|
|
+ const res = await updateStatus({ status: e, id })
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.get_charts()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ filterModalConfirm() {
|
|
|
+ this.showChartModal = false
|
|
|
+ this.get_charts()
|
|
|
+ },
|
|
|
logHandle(d) {
|
|
|
window.log({ c: 'requirement', d })
|
|
|
},
|
|
|
- getTableData() { // 查询
|
|
|
+ changeTab(e) {
|
|
|
+ this.nowTab = e
|
|
|
+ if (this.nowTab === 'charts') {
|
|
|
+ this.get_charts()
|
|
|
+ } else {
|
|
|
+ this.chartData = {}
|
|
|
+ this.getTableData()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ get_charts() {
|
|
|
+ this.updateChartSearchFormValue()
|
|
|
+ this.getSearchFormHandle()
|
|
|
+ this.get_chartList()
|
|
|
+ },
|
|
|
+ getSearchFormHandle() {
|
|
|
if (this.bizId === -1) return
|
|
|
for (const key in this.searchForm) { // 接口不接受空值的处理
|
|
|
if (this.searchForm[key] === '' || this.searchForm[key] === null) {
|
|
|
delete this.searchForm[key]
|
|
|
}
|
|
|
}
|
|
|
- if (this.requirementName) { // 判断需求名称
|
|
|
- this.searchForm.name = this.requirementName
|
|
|
- } else {
|
|
|
- this.searchForm.name = ''
|
|
|
- }
|
|
|
if (this.searchForm.date) {
|
|
|
this.searchForm.createStartTime = this.searchForm.date[0]
|
|
|
this.searchForm.createEndTime = this.searchForm.date[1]
|
|
@@ -377,25 +512,91 @@ export default {
|
|
|
|
|
|
this.searchForm.pageSize = this.pageSize
|
|
|
this.searchForm.curIndex = this.curIndex
|
|
|
+ },
|
|
|
+ getTableData() { // 查询
|
|
|
+ // if (this.bizId === -1) return
|
|
|
+ // for (const key in this.searchForm) { // 接口不接受空值的处理
|
|
|
+ // if (this.searchForm[key] === '' || this.searchForm[key] === null) {
|
|
|
+ // delete this.searchForm[key]
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // if (this.searchForm.date) {
|
|
|
+ // this.searchForm.createStartTime = this.searchForm.date[0]
|
|
|
+ // this.searchForm.createEndTime = this.searchForm.date[1]
|
|
|
+ // } else {
|
|
|
+ // delete this.searchForm.createStartTime
|
|
|
+ // delete this.searchForm.createEndTime
|
|
|
+ // }
|
|
|
+ // this.searchForm.bizId = this.bizId
|
|
|
+ // this.loading = true
|
|
|
|
|
|
+ // this.searchForm.pageSize = this.pageSize
|
|
|
+ // this.searchForm.curIndex = this.curIndex
|
|
|
+ this.getSearchFormHandle()
|
|
|
getRequirement(this.searchForm).then(res => {
|
|
|
this.tableData = res.data.list
|
|
|
this.total = res.data.total
|
|
|
this.loading = false
|
|
|
})
|
|
|
},
|
|
|
+ async get_chartList() {
|
|
|
+ this.loading = true
|
|
|
+ const res = await getChartData(this.searchForm)
|
|
|
+ this.chartData = res.data
|
|
|
+ this.get_chartListDetial(res.data.data[0].code)
|
|
|
+ },
|
|
|
+ async get_chartListDetial(code) {
|
|
|
+ if (code) {
|
|
|
+ this.searchForm.code = code
|
|
|
+ }
|
|
|
+ const dataList = await getChartListData(this.searchForm)
|
|
|
+ this.tableData = dataList.data.list
|
|
|
+ this.total = dataList.total
|
|
|
+ this.tableTitle = dataList.data.title
|
|
|
+ this.loading = false
|
|
|
+ },
|
|
|
async showRequirementEnum() {
|
|
|
const res = await showRequirementEnum()
|
|
|
if (res.code === 200) {
|
|
|
+ // 类型
|
|
|
+ res.data.type.map(t => {
|
|
|
+ t.value = t.code
|
|
|
+ t.label = t.msg
|
|
|
+ })
|
|
|
+ // 来源
|
|
|
+ res.data.sourceType.map(t => {
|
|
|
+ t.value = t.code
|
|
|
+ t.label = t.msg
|
|
|
+ })
|
|
|
+ // 优先级
|
|
|
+ res.data.priority.map(t => {
|
|
|
+ t.value = t.code
|
|
|
+ t.label = t.msg
|
|
|
+ })
|
|
|
this.searchInfo = res.data
|
|
|
+ this.updateChartSlectOption('type', res.data.type)
|
|
|
+ this.updateChartSlectOption('sourceTypeList', res.data.sourceType)
|
|
|
+ this.updateChartSlectOption('priorityList', res.data.priority)
|
|
|
}
|
|
|
const res1 = await projectListProject({ bizId: this.bizId })
|
|
|
if (res1.code === 200) {
|
|
|
- this.AttributionItems = res1.data
|
|
|
+ const AttributionItems = res1.data.map(t => ({
|
|
|
+ ...t,
|
|
|
+ label: t.name,
|
|
|
+ value: t.id
|
|
|
+ }))
|
|
|
+ this.AttributionItems = AttributionItems
|
|
|
+ this.updateChartSlectOption('belongingProject', AttributionItems)
|
|
|
}
|
|
|
const res2 = await configShowRequireStatusEnum(this.bizId)
|
|
|
if (res2.code === 200) {
|
|
|
- this.requiredStatus = res2.data.requirementStatus
|
|
|
+ const requiredStatus = res2.data.requirementStatus.map(t => ({
|
|
|
+ ...t,
|
|
|
+ label: t.msg,
|
|
|
+ value: t.code
|
|
|
+ }))
|
|
|
+ this.requiredStatus = requiredStatus
|
|
|
+ this.updateChartSlectOption('statusList', requiredStatus)
|
|
|
}
|
|
|
const res3 = await settingQueryBizRqmtOrntList(this.bizId)
|
|
|
if (res3.code === 200) { // 需求方向
|
|
@@ -495,7 +696,7 @@ export default {
|
|
|
// }
|
|
|
// this.getClient(filter.appId)
|
|
|
Object.assign(this.searchForm, filter)
|
|
|
- this.requirementName = filter.name
|
|
|
+ // this.requirementName = filter.name
|
|
|
this.curIndex = 1
|
|
|
this.getTableData()
|
|
|
}
|
|
@@ -516,42 +717,110 @@ export default {
|
|
|
this.getFilterList()
|
|
|
},
|
|
|
reset() {
|
|
|
- this.$set(this.searchForm, 'id', '')
|
|
|
- this.$set(this.searchForm, 'pm', '')
|
|
|
- this.$set(this.searchForm, 'priorityList', [])
|
|
|
- this.$set(this.searchForm, 'belongingProject', '')
|
|
|
- this.$set(this.searchForm, 'sourceType', '')
|
|
|
- this.$set(this.searchForm, 'creator', '')
|
|
|
- this.$set(this.searchForm, 'type', '')
|
|
|
- this.$set(this.searchForm, 'containStatus', [])
|
|
|
- this.$set(this.searchForm, 'comparisonOperator', '')
|
|
|
- this.$set(this.searchForm, 'days', '')
|
|
|
- this.$set(this.searchForm, 'rqmtProposer', '')
|
|
|
- this.$set(this.searchForm, 'sourceTypeList', [])
|
|
|
- this.$set(this.searchForm, 'isFromDpm', '')
|
|
|
- this.$set(this.searchForm, 'date', [])
|
|
|
- this.$message({
|
|
|
- message: '已重置',
|
|
|
- type: 'success',
|
|
|
- duration: 1000,
|
|
|
- offset: 150
|
|
|
- })
|
|
|
- this.getTableData()
|
|
|
+ // this.$set(this.searchForm, 'id', '')
|
|
|
+ // this.$set(this.searchForm, 'pm', '')
|
|
|
+ // this.$set(this.searchForm, 'priorityList', [])
|
|
|
+ // this.$set(this.searchForm, 'belongingProject', '')
|
|
|
+ // this.$set(this.searchForm, 'sourceType', '')
|
|
|
+ // this.$set(this.searchForm, 'creator', '')
|
|
|
+ // this.$set(this.searchForm, 'type', '')
|
|
|
+ // this.$set(this.searchForm, 'containStatus', [])
|
|
|
+ // this.$set(this.searchForm, 'comparisonOperator', '')
|
|
|
+ // this.$set(this.searchForm, 'days', '')
|
|
|
+ // this.$set(this.searchForm, 'rqmtProposer', '')
|
|
|
+ // this.$set(this.searchForm, 'sourceTypeList', [])
|
|
|
+ // this.$set(this.searchForm, 'isFromDpm', '')
|
|
|
+ // this.$set(this.searchForm, 'date', [])
|
|
|
+ // this.$message({
|
|
|
+ // message: '已重置',
|
|
|
+ // type: 'success',
|
|
|
+ // duration: 1000,
|
|
|
+ // offset: 150
|
|
|
+ // })
|
|
|
+ // 重置
|
|
|
+ this.searchForm = {
|
|
|
+ ...this.searchForm,
|
|
|
+ id: '',
|
|
|
+ pm: '',
|
|
|
+ priorityList: [],
|
|
|
+ belongingProject: '',
|
|
|
+ sourceType: '',
|
|
|
+ creator: '',
|
|
|
+ type: '',
|
|
|
+ containStatus: [],
|
|
|
+ comparisonOperator: '',
|
|
|
+ days: '',
|
|
|
+ rqmtProposer: '',
|
|
|
+ sourceTypeList: [],
|
|
|
+ isFromDpm: '',
|
|
|
+ date: []
|
|
|
+ }
|
|
|
+ if (this.nowTab === 'charts') {
|
|
|
+ this.searchForm = { ...this.searchForm, rqmtOrntIds: [], name: '', statusList: [] }
|
|
|
+ }
|
|
|
+ if (this.nowTab === 'charts') {
|
|
|
+ this.get_charts()
|
|
|
+ } else {
|
|
|
+ this.getTableData()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ async remoteMethod(query) {
|
|
|
+ // 人员查询
|
|
|
+ if (query !== '') {
|
|
|
+ // this.loading = true
|
|
|
+ const res = await getPerson({ memberIDAP: query })
|
|
|
+ const obj = {}
|
|
|
+ this.options = res.data.reduce((cur, next) => {
|
|
|
+ obj[next.idap] ? '' : obj[next.idap] = true && cur.push(next)
|
|
|
+ return cur
|
|
|
+ }, [])
|
|
|
+ // this.loading = false
|
|
|
+ } else {
|
|
|
+ this.options = []
|
|
|
+ }
|
|
|
+ this.updateChartSlectOption('pm', this.options)
|
|
|
+ this.updateChartSlectOption('rqmtProposer', this.options)
|
|
|
},
|
|
|
getToRequirementDetails(id) { // table点击跳转
|
|
|
const bizId_id = EncryptId(`${this.bizId}_${id}`)
|
|
|
- if (this.newTabOpen) {
|
|
|
+ if (localStorage.getItem('openPageHandle') === 'blank') {
|
|
|
const newTab = this.$router.resolve({ name: '需求详情', query: { bizId_id: bizId_id }})
|
|
|
window.open(newTab.href, '_blank')
|
|
|
} else {
|
|
|
this.$router.push({ name: '需求详情', query: { bizId_id: bizId_id }})
|
|
|
}
|
|
|
+ },
|
|
|
+ chartSearchFormChange(key, value) {
|
|
|
+ console.log(key, value, this.chartSearchFormRenderData)
|
|
|
+ this.searchForm[key] = value
|
|
|
+ },
|
|
|
+ updateChartSlectOption(key, option) {
|
|
|
+ this.chartSearchFormRenderData.map(t => {
|
|
|
+ if (t.key === key) {
|
|
|
+ t.option = option
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ updateChartSearchFormValue() {
|
|
|
+ this.chartSearchFormRenderData.map(t => {
|
|
|
+ t.value = this.searchForm[t.key]
|
|
|
+ })
|
|
|
+ console.log(this.searchForm, this.chartSearchFormRenderData)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
+.search_box {
|
|
|
+ .item {
|
|
|
+ width: 270px;
|
|
|
+ margin-right: 15px;
|
|
|
+ .queryName {
|
|
|
+ min-width: 80px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
.new-tab-open {
|
|
|
position: absolute;
|
|
|
left: 120px;
|
|
@@ -613,6 +882,13 @@ export default {
|
|
|
background: rgba(245,108,108,0.17);
|
|
|
color: rgba(245,108,108,1);
|
|
|
}
|
|
|
+.subtitle {
|
|
|
+ color: #333;
|
|
|
+ font-size: 16px;
|
|
|
+ background: #fff;
|
|
|
+ font-weight: 700;
|
|
|
+ padding: 16px 8px;
|
|
|
+}
|
|
|
</style>
|
|
|
|
|
|
<style>
|
|
@@ -646,26 +922,60 @@ export default {
|
|
|
|
|
|
</style>
|
|
|
<style scoped lang="scss">
|
|
|
+@mixin setStatus($color) {
|
|
|
+ input {
|
|
|
+ color:$color;
|
|
|
+ border: 1px solid $color;
|
|
|
+ }
|
|
|
+ /deep/.el-select__caret{
|
|
|
+ color:$color;
|
|
|
+ }
|
|
|
+ /deep/.el-input__inner{
|
|
|
+ color:$color;
|
|
|
+ border-color: $color;
|
|
|
+ }
|
|
|
+ /deep/.el-input__inner:focus {
|
|
|
+ border-color: $color;
|
|
|
+ }
|
|
|
+}
|
|
|
+.status0 {
|
|
|
+ @include setStatus(#409EFF)
|
|
|
+}
|
|
|
+.status1{
|
|
|
+ @include setStatus(#FF8952)
|
|
|
+}
|
|
|
+.status2 {
|
|
|
+ @include setStatus(#7ED321)
|
|
|
+}
|
|
|
.stylus-head {
|
|
|
position: relative;
|
|
|
}
|
|
|
.filter {
|
|
|
- font-size: 14px;
|
|
|
- width: 100%;
|
|
|
- padding: 15px 11px 0px 15px;
|
|
|
- color: #606266;
|
|
|
- cursor: pointer;
|
|
|
- .mine-filter {
|
|
|
- .filter-item {
|
|
|
- display: inline-block;
|
|
|
- width: 15%;
|
|
|
- color: #409EFF;
|
|
|
- margin-right: 15px;
|
|
|
- overflow: hidden;
|
|
|
- text-overflow:ellipsis;
|
|
|
- white-space: nowrap;
|
|
|
- // margin-bottom: 5px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: baseline;
|
|
|
+ margin-top: 15px;
|
|
|
+ .filterWrap {
|
|
|
+ display: flex;
|
|
|
+ align-items: baseline;
|
|
|
+ .title {
|
|
|
+ width: 100px;
|
|
|
}
|
|
|
+ .itemBox {
|
|
|
+ .item {
|
|
|
+ display: inline-block;
|
|
|
+ margin-right: 20px;
|
|
|
+ margin-bottom: 10px;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .btn {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #00A0FF;
|
|
|
+ cursor: pointer;
|
|
|
+ min-width: 80px;
|
|
|
+ text-align: center;
|
|
|
}
|
|
|
}
|
|
|
</style>
|