taskIndex.vue 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  1. <template>
  2. <div class="bgborder" style="background-color:#F2F3F6;min-height:calc(100vh - 80px);padding:0 10px 10px 10px">
  3. <div class="stylus-head">
  4. <mainTitle
  5. title="任务"
  6. btn-text="新建任务"
  7. :tab-show="true"
  8. @btn-handle="open_created"
  9. @change-tab="changeTab"
  10. />
  11. <div v-if="nowTab === 'charts'" class="chartView">
  12. <chartView
  13. :data="chartData"
  14. :type-option-list="typeOptionList"
  15. :chart-search-data="form_task"
  16. @search="get_charts()"
  17. @changeList="(code) => get_chartListDetial(code)"
  18. >
  19. <div slot="searchBox">
  20. <div class="Layout">
  21. <div class="Layout">
  22. <div class="chartSearchTitle">模块</div>
  23. <el-cascader v-model="form_task.moduleIds" size="small" clearable collapse-tags :props="props" :options="business_platform_Modular" placeholder="请选择" style="width:77% !important;" @change="get_charts()" />
  24. </div>
  25. <span class="screen" style="text-align:right; width: auto" @click="showChartModal = true">更多筛选</span>
  26. </div>
  27. </div>
  28. </chartView>
  29. </div>
  30. <div v-if="nowTab === 'list'" class="search_box">
  31. <div class="Layout" style="padding: 5px 0 0 15px">
  32. <div>
  33. <el-form :model="form_task" class="Layout">
  34. <div class="Layout_flex_end item">
  35. <div class="queryName">任务名称</div>
  36. <el-input v-model="form_task.name" size="small" clearable class="input" placeholder="请输入标题或ID或望岳ID" @change="get_taskList()" />
  37. </div>
  38. <div class="Layout item">
  39. <div class="queryName">状态</div>
  40. <el-select v-model="form_task.statusList" size="small" class="input" multiple clearable filterable placeholder="请选择" @change="get_taskList()">
  41. <el-option v-for="item in daStatus" :key="item.value" :label="item.label" :value="item.value" />
  42. </el-select>
  43. </div>
  44. <div class="Layout item">
  45. <div class="queryName">模块</div>
  46. <el-cascader v-model="form_task.moduleIds" size="small" class="input" clearable collapse-tags :props="props" :options="business_platform_Modular" placeholder="请选择" @change="get_taskList()" />
  47. </div>
  48. </el-form>
  49. </div>
  50. <span class="screen" @click="showSelect">{{ goodName }}</span>
  51. </div>
  52. <div v-show="DetailedScreening" class="stylus-more">
  53. <div>
  54. <div class="Layout">
  55. <el-form :model="form_task" class="flex_start">
  56. <div class="Layout item">
  57. <div class="queryName">所属项目</div>
  58. <el-select v-model="form_task.projectId" size="small" class="input" clearable filterable placeholder="请选择">
  59. <el-option v-for="item in projectList" :key="item.value" :label="item.label" :value="item.value" />
  60. </el-select>
  61. </div>
  62. <div class="Layout item">
  63. <div class="queryName">所属需求</div>
  64. <el-select v-model="form_task.requireId" size="small" class="input" clearable filterable placeholder="请选择">
  65. <el-option v-for="item in demandList" :key="item.value" :label="item.label" :value="item.value" />
  66. </el-select>
  67. </div>
  68. <div class="Layout item">
  69. <div class="queryName">来自望岳</div>
  70. <el-select v-model="form_task.isFromDpm" size="small" class="input" clearable filterable placeholder="请选择">
  71. <el-option v-for="item in isFromDpmList" :key="item.value" :label="item.label" :value="item.value" />
  72. </el-select>
  73. </div>
  74. </el-form>
  75. </div>
  76. <div class="Layout" style="margin: 15px 0;">
  77. <el-form :model="form_task" class="flex_start">
  78. <div class="Layout item">
  79. <div class="queryName">优先级</div>
  80. <el-select v-model="form_task.priority" size="small" class="input" clearable filterable placeholder="请选择">
  81. <el-option v-for="item in arr_priority" :key="item.value" :label="item.label" :value="item.value" />
  82. </el-select>
  83. </div>
  84. <div class="Layout item">
  85. <div class="queryName">负责人</div>
  86. <el-select
  87. v-model="form_task.PersonInCharge"
  88. class="input"
  89. clearable
  90. filterable
  91. remote
  92. placeholder="请输入姓名或邮箱前缀"
  93. :remote-method="remoteMethod"
  94. :loading="loading"
  95. size="small"
  96. >
  97. <el-option v-for="item in options" :key="item.idap" :label="item.name" :value="test2(item, 0)">
  98. <div class="flex_start">
  99. <div class="deptName">{{ item.deptName }}</div>
  100. <div style="min-width:80px">{{ item.name }}</div>
  101. <div class="deptName">{{ item.idap }}</div>
  102. </div>
  103. </el-option>
  104. </el-select>
  105. </div>
  106. <div class="Layout item">
  107. <div class="queryName">健康状态</div>
  108. <el-select v-model="form_task.stage" size="small" class="input" clearable filterable placeholder="请选择">
  109. <el-option v-for="item in healthStage" :key="item.value" :label="item.label" :value="item.value" />
  110. </el-select>
  111. </div>
  112. </el-form>
  113. </div>
  114. <div class="Layout" style="margin: 15px 0;">
  115. <el-form :model="form_task" class="flex_start">
  116. <div class="Layout item">
  117. <div class="queryName" style="width:86px;">创建人</div>
  118. <el-select
  119. v-model="form_task.creater"
  120. class="input"
  121. clearable
  122. filterable
  123. remote
  124. placeholder="请输入姓名或邮箱前缀"
  125. :remote-method="remoteMethod"
  126. :loading="loading"
  127. size="small"
  128. style="width: 82%;"
  129. >
  130. <el-option v-for="item in options" :key="item.idap" :label="item.name" :value="test2(item, 0)">
  131. <div class="flex_start">
  132. <div class="deptName">{{ item.deptName }}</div>
  133. <div style="min-width:80px">{{ item.name }}</div>
  134. <div class="deptName">{{ item.idap }}</div>
  135. </div>
  136. </el-option>
  137. </el-select>
  138. </div>
  139. <div class="Layout item">
  140. <div class="queryName">创建日期</div>
  141. <el-date-picker
  142. v-model="form_task.date"
  143. type="daterange"
  144. align="right"
  145. unlink-panels
  146. range-separator="至"
  147. start-placeholder="开始日期"
  148. end-placeholder="结束日期"
  149. size="small"
  150. class="input"
  151. style="min-width: 476px"
  152. value-format="yyyy-MM-dd HH:mm:ss"
  153. :default-time="['00:00:00','23:59:59']"
  154. :picker-options="pickerOptions"
  155. />
  156. </div>
  157. </el-form>
  158. </div>
  159. <div align="right">
  160. <el-button type="text" @click="showSaveSearch = true">保存筛选项</el-button>
  161. <el-button type="primary" size="mini" @click="get_taskList(form_task)">筛 选</el-button>
  162. <el-button size="mini" @click="query_Reset">重 置</el-button>
  163. </div>
  164. </div>
  165. </div>
  166. <div v-if="filterList.length && filterList.length > 0" class="filter">
  167. <div class="filterWrap">
  168. <div class="title">我的过滤器:</div>
  169. <div class="itemBox">
  170. <el-tag v-for="item in filterList" :key="item.id" class="item" @click="getFilterItem(item.id)">{{ item.name }}</el-tag>
  171. </div>
  172. </div>
  173. <div class="btn">
  174. <span @click.stop="showEditSearch = true">管理过滤器</span>
  175. </div>
  176. </div>
  177. </div>
  178. </div>
  179. <div class="stylus-content">
  180. <div v-if="nowTab === 'charts'" class="subtitle">{{ tableTitle }}</div>
  181. <el-table
  182. v-loading="table_loading"
  183. :data="task_table"
  184. style="width: 100%;"
  185. highlight-current-row
  186. :header-cell-style="{ 'background': nowTab === 'charts' ? '#F7F7F7' : '#fff', 'color':'rgba(74,74,74,1)','font-size':'14px','font-weight':'500' }"
  187. :cell-style="{ 'font-size':'14px','color':'rgba(102,102,102,1)' }"
  188. size="small"
  189. show-overflow-tooltip="true"
  190. >
  191. <el-table-column label="优先级" width="90" prop="priority" sortable align="right">
  192. <template slot-scope="scope">
  193. <div class="div_priority" :style="{background: priorityColors[scope.row.priority]}">{{ scope.row.priorityString }}</div>
  194. </template>
  195. </el-table-column>
  196. <el-table-column label="任务名称" min-width="250" show-overflow-tooltip align="left">
  197. <template slot-scope="scope">
  198. <span style="font-size: 12px;color: rgba(167,174,188,1);">
  199. {{ scope.row.taskIdSting }}
  200. <span
  201. v-if="scope.row.tagNotification !== null && scope.row.status !== -2"
  202. :class="{
  203. 'tagNotification': scope.row.tagType === 0,
  204. 'tagNotification1': scope.row.tagType === 1
  205. }"
  206. >
  207. {{ scope.row.tagNotification }}
  208. </span>
  209. <span v-if="scope.row.status === -2" class="tagNotification1"> {{ 'hold' }} </span>
  210. </span><br>
  211. <span class="stylus-hover" @click="link_task(scope.row.id)">{{ scope.row.name }}</span>
  212. </template>
  213. </el-table-column>
  214. <el-table-column label="状态" min-width="150" align="center" show-overflow-tooltip>
  215. <template slot-scope="scope">
  216. <el-select
  217. v-if="nowTab === 'charts'"
  218. v-model="scope.row.status"
  219. :size="size"
  220. placeholder=""
  221. @change="(e) => statusChange(e, scope.row.id)"
  222. >
  223. <el-option v-for="o in scope.row.availableStatusList" :key="o.code" :label="o.name" :value="o.code" />
  224. </el-select>
  225. <span v-else>{{ scope.row.statusString }}</span>
  226. </template>
  227. </el-table-column>
  228. <el-table-column label="健康状态" width="150" align="center" show-overflow-tooltip>
  229. <template slot-scope="scope">{{ scope.row.stageString }}</template>
  230. </el-table-column>
  231. <el-table-column label="开发负责人" min-width="100" align="center">
  232. <template
  233. slot-scope="scope"
  234. >{{ scope.row.rdObject !== null? scope.row.rdObject.name: '' }}</template>
  235. </el-table-column>
  236. <el-table-column label="测试负责人" min-width="100" align="center">
  237. <template
  238. slot-scope="scope"
  239. >{{ scope.row.qaObject !== null?scope.row.qaObject.name: '' }}</template>
  240. </el-table-column>
  241. <el-table-column label="所属模块" width="150" align="center" show-overflow-tooltip>
  242. <template slot-scope="scope">{{ scope.row.moduleInfoName }}</template>
  243. </el-table-column>
  244. <el-table-column label="是否免测" min-width="80" align="center">
  245. <template slot-scope="scope">{{ scope.row.noTestString }}</template>
  246. </el-table-column>
  247. <el-table-column label="缺陷数量" width="250" align="center" show-overflow-tooltip>
  248. <template slot-scope="scope">{{ scope.row.bugCount }}</template>
  249. </el-table-column>
  250. <el-table-column label="所属需求" min-width="250" align="center" show-overflow-tooltip>
  251. <template slot-scope="scope">{{ scope.row.requireName }}</template>
  252. </el-table-column>
  253. <el-table-column label="所属项目" min-width="250" align="center" show-overflow-tooltip>
  254. <template slot-scope="scope">{{ scope.row.projectName }}</template>
  255. </el-table-column>
  256. <el-table-column label="创建人" min-width="120" align="center" show-overflow-tooltip>
  257. <template slot-scope="scope">{{ scope.row.createObject.name }}</template>
  258. </el-table-column>
  259. <el-table-column label="创建日期" min-width="120" align="center" show-overflow-tooltip>
  260. <template slot-scope="scope">{{ scope.row.createTime }}</template>
  261. </el-table-column>
  262. </el-table>
  263. <div align="right">
  264. <el-pagination
  265. background
  266. :current-page="currentPage"
  267. :page-sizes="[15,30,45,total]"
  268. :page-size="pageSize"
  269. layout="total, sizes, prev, pager, next, jumper"
  270. :total="total"
  271. @size-change="handleSizeChange"
  272. @current-change="handleCurrentChange"
  273. />
  274. </div>
  275. </div>
  276. <!-- 弹窗 -->
  277. <openDialog v-if="dialog_open" ref="task_createdUpdata" />
  278. <normal-dialog :show-dialog="showSaveSearch" :title="'保存筛选项'" :width="'35%'" @confirm="saveSearch('searchForm')" @cancel="showSaveSearch=false">
  279. <div v-if="showSaveSearch" class="file-dialog">
  280. <el-form ref="searchForm" :model="searchForm" :rules="searchFormRules" label-width="100px">
  281. <el-form-item label="过滤器名称" prop="name">
  282. <el-input v-model="searchForm.name" placeholder="不超过50个字符" />
  283. </el-form-item>
  284. </el-form>
  285. </div>
  286. </normal-dialog>
  287. <normal-dialog :show-footer="false" :show-dialog="showEditSearch" :title="'管理过滤器'" :width="'65%'" @cancel="showEditSearch=false">
  288. <filter-list :show-filter="showEditSearch" :filter-type="2" @deleteFilter="deleteFilter" />
  289. </normal-dialog>
  290. <filterModal
  291. title="筛选项"
  292. :show-dialog="showChartModal"
  293. @reset="query_Reset"
  294. @cancel="showChartModal = false"
  295. @confirm="filterModalConfirm"
  296. >
  297. <div>
  298. <chartSearchForm
  299. :data="chartSearchFormRenderData"
  300. :loading="loading"
  301. :styles="{ marginBottom: '15px', width: '380px' }"
  302. @change="chartSearchFormChange"
  303. @getOption="(key, q, utilName) => remoteMethod(q)"
  304. />
  305. </div>
  306. </filterModal>
  307. </div>
  308. </template>
  309. <script>
  310. const _ = require('lodash')
  311. import { EncryptId } from '@/utils/crypto-js.js'
  312. import { mapGetters } from 'vuex'
  313. import {
  314. taskList,
  315. configShowTaskEnum,
  316. memberQueryMemberInfoByIDAPorName,
  317. configShowRequirementVersionEnum,
  318. projectListProject,
  319. getFilterList,
  320. configShowTaskStatusEnum,
  321. createFilter,
  322. filterGetFilter,
  323. getChartListData,
  324. getChartData,
  325. updateStatus
  326. } from '@/api/taskIndex' // ajax
  327. import filterModal from '@/components/filterModal'
  328. import { settingQueryBizModuleList } from '@/api/defectManage'
  329. import openDialog from '@/views/projectManage/dialog_vue'
  330. // 过滤器
  331. import filterList from '@/views/projectManage/components/filterList'
  332. import normalDialog from '@/components/dialog/normalDialog'
  333. import mainTitle from '@/components/mainTitle'
  334. import chartView from '@/components/chartView'
  335. import chartSearchFormData from './renderData/chartSearchForm'
  336. import chartSearchForm from '@/components/searchHeader/searchForm'
  337. import '@/views/projectManage/publicCss/index.css'
  338. import '@/styles/PublicStyle/index.scss'
  339. export default {
  340. components: {
  341. openDialog,
  342. filterList,
  343. normalDialog,
  344. mainTitle,
  345. chartView,
  346. filterModal,
  347. chartSearchForm
  348. },
  349. data() {
  350. return {
  351. size: 'small',
  352. pickerOptions: {
  353. shortcuts: [{
  354. text: '最近一周',
  355. onClick(picker) {
  356. const end = new Date()
  357. const start = new Date()
  358. start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
  359. picker.$emit('pick', [start, end])
  360. }
  361. }, {
  362. text: '最近一个月',
  363. onClick(picker) {
  364. const end = new Date()
  365. const start = new Date()
  366. start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
  367. picker.$emit('pick', [start, end])
  368. }
  369. }, {
  370. text: '最近三个月',
  371. onClick(picker) {
  372. const end = new Date()
  373. const start = new Date()
  374. start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
  375. picker.$emit('pick', [start, end])
  376. }
  377. }]
  378. },
  379. header_show: true,
  380. props: {
  381. value: 'id',
  382. label: 'moduleName',
  383. children: 'childModules',
  384. multiple: true
  385. },
  386. isFromDpmList: [{ value: true, label: '是' }, { value: false, label: '否' }],
  387. priorityColors: ['#F56C6C', '#FF8952', '#F5E300', '#7ED321', '#61D3B8', '#69B3FF', '#BDBDBD'],
  388. arr_priority: [{ value: 0, label: 'P0' }, { value: 1, label: 'P1' }, { value: 2, label: 'P2' }, { value: 3, label: 'P3' }],
  389. dialog_open: false,
  390. curIndex: 1,
  391. pageSize: 15,
  392. goodName: '更多筛选',
  393. options: [],
  394. daStatus: [], // 任务状态筛选option
  395. healthStage: [],
  396. list: [],
  397. userInformation: localStorage.getItem('username'),
  398. userNames: localStorage.getItem('realname'),
  399. form_task: {
  400. viewType: '0'
  401. },
  402. noTest: [], // 是否免测
  403. BusinessLine: [], // 业务线
  404. appClient: [], // 涉及业务线
  405. arr_platform: [], // 平台数据
  406. business_platform_Modular: [], // 模块数据
  407. arr_taskName: [], // 任务名称数据
  408. projectList: [], // 归属项目数据
  409. demandList: [], // 需求list
  410. dialogFormVisible: false,
  411. currentPage: 0,
  412. DetailedScreening: false,
  413. total: 0,
  414. biz: '',
  415. isToOne: true,
  416. loading: false,
  417. table_loading: false,
  418. test: {},
  419. task_table: [],
  420. form: {},
  421. arry: [],
  422. filterList: [],
  423. showEditSearch: false, // 显示管理过滤器
  424. searchForm: { name: null }, // 筛选项obj
  425. searchFormRules: { name: [
  426. { required: true, message: '请输入筛选项名称', trigger: 'blur' },
  427. { min: 1, max: 50, message: '长度在 1 到 50 个字符', trigger: 'blur' }
  428. ] },
  429. showSaveSearch: false, // 显示保存筛选项对话框
  430. nowTab: 'list',
  431. chartData: {},
  432. typeOptionList: [
  433. { value: '0', label: '任务状态' },
  434. { value: '1', label: '任务等级' },
  435. { value: '2', label: '开发负责人' },
  436. { value: '3', label: '测试负责人' },
  437. { value: '4', label: '跟版客户端' },
  438. { value: '5', label: '直接归属' }
  439. ],
  440. showChartModal: false,
  441. tableTitle: '',
  442. chartSearchFormRenderData: _.cloneDeep(chartSearchFormData)
  443. }
  444. },
  445. computed: {
  446. ...mapGetters(['bizId'])
  447. },
  448. watch: {
  449. bizId() {
  450. this.get_taskList()
  451. this.get_taskSelect()
  452. this.getFilterList() // 筛选项保存
  453. }
  454. },
  455. created() {
  456. this.get_taskList()
  457. this.get_taskSelect()
  458. this.bugDataGet()
  459. this.$store.state.data.status = true
  460. },
  461. mounted() {
  462. this.$nextTick(() => {
  463. this.bugDataGet()
  464. this.getFilterList() // 筛选项保存
  465. })
  466. this.updateChartSlectOption('isFromDpm', this.isFromDpmList)
  467. this.updateChartSlectOption('priority', this.arr_priority)
  468. },
  469. destroyed() {
  470. this.$store.state.data.status = false
  471. },
  472. methods: {
  473. filterModalConfirm() {
  474. this.showChartModal = false
  475. this.get_charts()
  476. },
  477. logHandle(d) {
  478. window.log({ c: 'task', d })
  479. },
  480. changeTab(e) {
  481. this.nowTab = e
  482. if (this.nowTab === 'charts') {
  483. this.get_charts()
  484. } else {
  485. this.chartData = {}
  486. this.get_taskList()
  487. }
  488. },
  489. async statusChange(e, id) {
  490. console.log(e)
  491. const res = await updateStatus({ status: e, id })
  492. if (res.code === 200) {
  493. this.get_charts()
  494. }
  495. },
  496. get_charts() {
  497. this.updateChartSearchFormValue()
  498. this.form_taskHandle()
  499. this.get_chartList()
  500. },
  501. async get_chartList() {
  502. this.table_loading = true
  503. const res = await getChartData(this.form_task)
  504. this.chartData = res.data
  505. this.get_chartListDetial(res.data.data[0].code)
  506. },
  507. async get_chartListDetial(code) {
  508. if (code) {
  509. this.form_task.code = code
  510. }
  511. const dataList = await getChartListData(this.form_task)
  512. this.task_table = dataList.data.list
  513. this.total = dataList.total
  514. this.tableTitle = dataList.data.title
  515. this.table_loading = false
  516. },
  517. test2(item, e) {
  518. // 获取团队人员信息
  519. if (typeof this.test[item.idap] === 'undefined') {
  520. item.role = e
  521. this.test[item.idap] = item
  522. }
  523. return item.idap
  524. },
  525. // 保存筛选项
  526. saveSearch(formName) { // 保存筛选项
  527. this.$refs[formName].validate((valid) => {
  528. if (valid) {
  529. this.stratAndEnd = this.stratAndEnd ? this.stratAndEnd : []
  530. this.form_task.createStartTime = this.stratAndEnd[0] || null
  531. this.form_task.createEndTime = this.stratAndEnd[1] || null
  532. const isExistName = this.filterList.some(item => {
  533. return item.name === this.searchForm.name
  534. })
  535. if (isExistName) {
  536. this.$message({ showClose: true, message: '筛选项名称重名', type: 'error' })
  537. } else {
  538. this.toSave()
  539. }
  540. } else {
  541. this.$message({ showClose: true, message: '筛选项名称不能为空', type: 'error' })
  542. return false
  543. }
  544. })
  545. },
  546. // 保存过滤器
  547. async toSave() {
  548. const saveObj = _.cloneDeep(this.form_task)
  549. delete saveObj.curIndex
  550. delete saveObj.pageSize
  551. const res = await createFilter({
  552. name: this.searchForm.name,
  553. content: JSON.stringify(saveObj),
  554. bizId: this.bizId,
  555. filterType: 2
  556. })
  557. if (res.code === 200) {
  558. this.$message({ showClose: true, message: '保存成功', type: 'success' })
  559. this.showSaveSearch = false
  560. this.getFilterList()
  561. this.searchForm.name = null
  562. }
  563. },
  564. async getFilterList() { // 获取过滤器列表
  565. const params = {
  566. bizId: this.bizId,
  567. filterType: 2
  568. }
  569. const res = await getFilterList(params)
  570. this.filterList = res.data
  571. },
  572. deleteFilter() {
  573. this.$router.push({ path: this.$route.path })
  574. this.getFilterList()
  575. },
  576. form_taskHandle() {
  577. if (this.bizId === -1) return
  578. // 查询
  579. if (this.isToOne) {
  580. this.curIndex = 1
  581. this.currentPage = 1
  582. }
  583. this.table_loading = true
  584. this.form_task.bizId = this.bizId
  585. this.form_task.pageSize = this.pageSize
  586. this.form_task.curIndex = this.curIndex
  587. for (const key in this.form_task) { // 接口不接受空值的处理
  588. if (this.form_task[key] === '') {
  589. delete this.form_task[key]
  590. }
  591. }
  592. if (this.form_task.date) {
  593. this.form_task.createTimeBegin = this.form_task.date[0]
  594. this.form_task.createTimeEnd = this.form_task.date[1]
  595. } else {
  596. delete this.form_task.createTimeBegin
  597. delete this.form_task.createTimeEnd
  598. }
  599. },
  600. get_taskList(e) {
  601. // if (this.bizId === -1) return
  602. // // 查询
  603. // if (this.isToOne) {
  604. // this.curIndex = 1
  605. // this.currentPage = 1
  606. // }
  607. // this.table_loading = true
  608. // this.form_task.bizId = this.bizId
  609. // this.form_task.pageSize = this.pageSize
  610. // this.form_task.curIndex = this.curIndex
  611. // for (const key in this.form_task) { // 接口不接受空值的处理
  612. // if (this.form_task[key] === '') {
  613. // delete this.form_task[key]
  614. // }
  615. // }
  616. // if (this.form_task.date) {
  617. // this.form_task.createTimeBegin = this.form_task.date[0]
  618. // this.form_task.createTimeEnd = this.form_task.date[1]
  619. // } else {
  620. // delete this.form_task.createTimeBegin
  621. // delete this.form_task.createTimeEnd
  622. // }
  623. this.form_taskHandle()
  624. taskList(this.form_task).then(res => {
  625. this.task_table = res.data
  626. this.total = res.total
  627. this.table_loading = false
  628. })
  629. configShowRequirementVersionEnum({ bizId: this.bizId }).then(res => {
  630. // 获取需求(查询)
  631. const demandList = res.data.map(t => ({
  632. ...t,
  633. label: t.name,
  634. value: t.id
  635. }))
  636. this.demandList = demandList
  637. this.updateChartSlectOption('requireId', demandList)
  638. })
  639. this.isToOne = true
  640. },
  641. async remoteMethod(query) {
  642. // 人员查询
  643. if (query !== '') {
  644. this.loading = true
  645. const res = await memberQueryMemberInfoByIDAPorName({ memberIDAP: query })
  646. const obj = {}
  647. this.options = res.data.reduce((cur, next) => {
  648. obj[next.idap] ? '' : obj[next.idap] = true && cur.push(next)
  649. return cur
  650. }, [])
  651. this.loading = false
  652. } else {
  653. this.options = []
  654. }
  655. this.updateChartSlectOption('PersonInCharge', this.options)
  656. this.updateChartSlectOption('creater', this.options)
  657. },
  658. showSelect() {
  659. this.DetailedScreening = !this.DetailedScreening
  660. this.goodName === '更多筛选' ? this.goodName = '收起筛选' : this.goodName = '更多筛选'
  661. },
  662. team_dates(e) {
  663. // 改变成员
  664. this.form.arry = []
  665. for (const i in e) {
  666. this.form.arry.push(this.test[e[i]])
  667. }
  668. this.arry = this.form.arry.map(item => {
  669. return { memberIDAP: item.idap, department: item.deptid, role: 0 }
  670. })
  671. },
  672. open_created() {
  673. // 打开弹窗
  674. this.dialog_open = true
  675. this.$nextTick(() => {
  676. this.$refs.task_createdUpdata.init(1)
  677. })
  678. },
  679. link_task(id) {
  680. const bizId_id = EncryptId(`${this.bizId}_${id}`)
  681. if (localStorage.getItem('openPageHandle') === 'self') {
  682. this.$router.push({ name: '任务详情', query: { bizId_id: bizId_id }})
  683. } else {
  684. const newTab = this.$router.resolve({ name: '任务详情', query: { bizId_id: bizId_id }})
  685. window.open(newTab.href, '_blank')
  686. }
  687. },
  688. query_Reset() {
  689. // 重置
  690. this.form_task = {
  691. ...this.form_task,
  692. bizId: '',
  693. status: '',
  694. stage: '',
  695. id: '',
  696. projectId: '',
  697. requireId: '',
  698. PersonInCharge: '',
  699. Participant: '',
  700. creater: '',
  701. isFromDpm: '',
  702. priority: '',
  703. date: []
  704. }
  705. if (this.nowTab === 'charts') {
  706. this.form_task = { ...this.form_task, moduleIds: [], name: '', statusList: [] }
  707. }
  708. this.updateChartSearchFormValue()
  709. if (this.nowTab === 'charts') {
  710. this.get_charts()
  711. } else {
  712. this.get_taskList()
  713. }
  714. // this.$message({
  715. // message: '已重置',
  716. // type: 'success',
  717. // duration: 1000,
  718. // offset: 150
  719. // })
  720. },
  721. handleSizeChange(size) {
  722. // 分页
  723. this.pageSize = size
  724. this.isToOne = false
  725. this.form_taskHandle()
  726. if (this.nowTab === 'charts') {
  727. this.get_chartListDetial()
  728. return
  729. }
  730. this.get_taskList(1)
  731. },
  732. handleCurrentChange(curIndex) {
  733. // 分页
  734. this.curIndex = curIndex
  735. this.currentPage = curIndex
  736. this.isToOne = false
  737. this.form_taskHandle()
  738. if (this.nowTab === 'charts') {
  739. this.get_chartListDetial()
  740. return
  741. }
  742. this.get_taskList()
  743. },
  744. async get_taskSelect() {
  745. if (this.bizId === -1) return
  746. // 下拉菜单数据
  747. const res = await configShowTaskEnum()
  748. if (res.code === 200) {
  749. const healthStage = res.data.taskStage.map(t => ({
  750. ...t,
  751. label: t.msg,
  752. value: t.code
  753. }))
  754. this.healthStage = healthStage
  755. this.updateChartSlectOption('stage', healthStage)
  756. this.noTest = res.data.noTest // 是否免测
  757. this.taskSource = res.data.taskSource // 归属需求
  758. this.appClient = res.data.appClient // 涉及客户端
  759. }
  760. const res1 = await configShowTaskStatusEnum(this.bizId)
  761. if (res1.code === 200) {
  762. const daStatus = res1.data.taskStatus.map(t => ({
  763. ...t,
  764. label: t.msg,
  765. value: t.code
  766. }))
  767. this.daStatus = daStatus
  768. this.updateChartSlectOption('statusList', daStatus)
  769. }
  770. const res2 = await projectListProject({ bizId: this.bizId })
  771. if (res2.code === 200) {
  772. const projectList = res2.data.map(t => ({
  773. ...t,
  774. label: t.name,
  775. value: t.id
  776. }))
  777. this.projectList = projectList
  778. this.updateChartSlectOption('projectId', projectList)
  779. }
  780. },
  781. bugDataGet() { // 所属模块
  782. this.biz = this.bizId
  783. if (this.bizId === -1) {
  784. this.biz = this.$store.state.global.bizId
  785. }
  786. settingQueryBizModuleList(this.biz).then(res => {
  787. this.business_platform_Modular = this.getRequireData(res.data)
  788. })
  789. },
  790. getRequireData(data) {
  791. for (let i = 0; i < data.length; i++) {
  792. data[i].childModules && data[i].childModules.length < 1 ? delete data[i].childModules : this.getRequireData(data[i].childModules)
  793. }
  794. return data
  795. },
  796. async getFilterItem(filterId) { // 获取单个过滤器
  797. const res = await filterGetFilter(filterId)
  798. if (res.code === 200) {
  799. const filter = JSON.parse(res.data.content)
  800. Object.assign(this.form_task, filter)
  801. this.curIndex = 1
  802. this.get_taskList()
  803. }
  804. },
  805. chartSearchFormChange(key, value) {
  806. console.log(key, value, this.chartSearchFormRenderData)
  807. this.form_task[key] = value
  808. },
  809. updateChartSlectOption(key, option) {
  810. this.chartSearchFormRenderData.map(t => {
  811. if (t.key === key) {
  812. t.option = option
  813. }
  814. })
  815. },
  816. updateChartSearchFormValue() {
  817. this.chartSearchFormRenderData.map(t => {
  818. t.value = this.form_task[t.key]
  819. })
  820. }
  821. }
  822. }
  823. </script>
  824. <style lang="scss" scoped>
  825. .chartView {
  826. .chartSearchTitle {
  827. width: 50px;
  828. color: #333333;
  829. font-size: 14px;
  830. }
  831. .screen {
  832. margin-left: 20px;
  833. }
  834. }
  835. .stylus-head {
  836. position: relative;
  837. }
  838. .new-tab-open {
  839. position: absolute;
  840. left: 120px;
  841. }
  842. .filter {
  843. display: flex;
  844. justify-content: space-between;
  845. align-items: baseline;
  846. margin-top: 15px;
  847. .filterWrap {
  848. display: flex;
  849. align-items: baseline;
  850. .title {
  851. width: 100px;
  852. }
  853. .itemBox {
  854. .item {
  855. display: inline-block;
  856. margin-right: 20px;
  857. margin-bottom: 10px;
  858. cursor: pointer;
  859. }
  860. }
  861. }
  862. .btn {
  863. font-size: 14px;
  864. color: #00A0FF;
  865. cursor: pointer;
  866. min-width: 80px;
  867. text-align: center;
  868. }
  869. }
  870. .subtitle {
  871. color: #333;
  872. font-size: 16px;
  873. background: #fff;
  874. font-weight: 700;
  875. padding: 16px 12px;
  876. }
  877. .search_box {
  878. .item {
  879. width: 270px;
  880. margin-right: 15px;
  881. .queryName {
  882. min-width: 80px;
  883. }
  884. }
  885. }
  886. </style>
  887. <style>
  888. .el-loading-mask {
  889. z-index: 8;
  890. }
  891. .requirement-xx .el-table .cell {
  892. padding: 5px 0;
  893. font-size: 14px;
  894. font-family: MicrosoftYaHei;
  895. }
  896. .requirement-xx .el-table .el-table__body tr:hover td { color: #409EFF; background: #EDF6FF; } /*hover时字体, 背景颜色*/
  897. .footer {
  898. text-align: right;
  899. margin: 1%;
  900. background-color: #ffffff;
  901. border-radius: 4px;
  902. }
  903. .bgborder .el-table .cell {
  904. box-sizing: border-box;
  905. overflow: hidden;
  906. text-overflow: ellipsis;
  907. word-break: break-all;
  908. line-height: 23px;
  909. padding-right: 10px;
  910. margin: -6px 0 -2px 0 !important;
  911. }
  912. .el-table .warning-row {
  913. background: oldlace;
  914. }
  915. .drop_down {
  916. font-size: 14px;
  917. color: #333333;
  918. }
  919. .requirement_el-dropdown-menu {
  920. max-height: 300px !important;
  921. max-width: 200px;
  922. overflow: auto !important;
  923. }
  924. .el-dropdown-menu__item:not(.is-disabled):hover {
  925. background-color: #f6f7fa;
  926. color: #606266;
  927. }
  928. .div_priority {
  929. display: inline-block;
  930. width: 38px;
  931. text-align: center;
  932. line-height: 24px;
  933. font-size: 14px;
  934. color: #fff;
  935. border-radius: 4px;
  936. margin-right: 30px;
  937. }
  938. .tagNotification {
  939. background: rgba(255,137,82,15%);
  940. color: #FF8952;
  941. padding: 0 5px;
  942. border-radius: 8px;
  943. margin-left: 10px;
  944. }
  945. .tagNotification1 {
  946. background: rgba(245,108,108,17%);
  947. color: #F56C6C;
  948. padding: 0 5px;
  949. border-radius: 8px;
  950. margin-left: 10px;
  951. }
  952. </style>
  953. <style lang="stylus" scoped>
  954. .stylus-head >>> .el-form-item__label
  955. color #333333
  956. font-weight 400
  957. .stylus-content >>> .el-table .el-table__body tr:hover td
  958. // color #409EFF !important
  959. background #EDF6FF
  960. .stylus-head >>> .el-divider--horizontal
  961. margin 10px 0
  962. .stylus-head >>> .el-form-item
  963. margin-bottom 0
  964. .stylus-head
  965. width 100%
  966. padding 15px
  967. margin-bottom: 10px
  968. background-color white
  969. border-radius 4px
  970. .stylus-title
  971. display flex
  972. justify-content space-between
  973. align-items center
  974. .stylus-more
  975. background rgba(252,252,252,1)
  976. border-radius 4px
  977. padding 15px
  978. min-height 100px
  979. margin-top 22px
  980. border 1px solid rgba(238,238,238,1)
  981. width 100%
  982. .stylus-content
  983. width 100%
  984. padding 0.3% 1% 1% 1%
  985. margin:0 auto
  986. background-color white
  987. border-radius 4px
  988. // min-height: calc(100vh - 143px);
  989. .stylus-hover:hover
  990. color #409EFF !important
  991. cursor pointer
  992. </style>