ProjectDetailDialog.vue 80 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507
  1. <template>
  2. <el-drawer
  3. :title="title"
  4. :visible.sync="visible"
  5. direction="rtl"
  6. :append-to-body="true"
  7. size="100%"
  8. >
  9. <el-card>
  10. <div style="width: 100%">
  11. <el-row style="font-size: 16px">
  12. <el-col :span="3" style="color: #1890ff"
  13. >项目名称:{{ rowData.name }}
  14. </el-col>
  15. <el-col :span="3"
  16. >项目预算:{{
  17. rowData.budget
  18. ? rowData.budget +
  19. this.getDictV('pro_projects_budget_unit', rowData.unit)
  20. : ''
  21. }}
  22. </el-col>
  23. <el-col :span="3"
  24. >项目经理:{{ rowData.responsibleUserName }}
  25. </el-col>
  26. <el-col :span="3">项目周期:{{ rowData.cycle }} </el-col>
  27. <el-col :span="3"
  28. >项目状态:
  29. {{ getDictV('pro_projects_status', rowData.status) }}</el-col
  30. >
  31. </el-row>
  32. </div>
  33. </el-card>
  34. <el-card class="card_2_box" style="height: calc(100vh - 130px)">
  35. <!-- <el-row style="padding-bottom: 12px">
  36. <dv-border-box-12
  37. class="card_2_1_box"
  38. :color="['rgb(255,255,255)', 'rgb(255,255,255)']"
  39. :backgroundColor="'rgb(255,255,255)'"
  40. >
  41. <div class="card_2_1_box_div_1">
  42. <el-steps :active="active" finish-status="success" simple>
  43. <el-step
  44. v-for="(item, index) in projectStepList"
  45. :key="index"
  46. :title="item"
  47. ></el-step>
  48. </el-steps>
  49. </div>
  50. <div class="card_2_1_box_div_2">
  51. <dv-percent-pond
  52. :title="(dialogForm.speedPercent || 0) + '%'"
  53. :config="{
  54. value: dialogForm.speedPercent || 0,
  55. localGradient: true,
  56. textColor: 'rgb(0,185,253)',
  57. formatter: ''
  58. }"
  59. style="width: 98%; height: 55%"
  60. />
  61. </div>
  62. </dv-border-box-12>
  63. </el-row> -->
  64. <el-row :gutter="24">
  65. <el-col :span="4">
  66. <p_search @search="getLeftData" />
  67. <ele-pro-table
  68. ref="table"
  69. row-key="id"
  70. :columns="columnsLeft"
  71. :datasource="leftTreeData"
  72. height="calc(100vh - 200px)"
  73. full-height="calc(100vh - 116px)"
  74. :default-expand-all="true"
  75. cache-key="project-initiationTable"
  76. :tree-props="{ children: 'projectList' }"
  77. :indent="15"
  78. :needPage="false"
  79. >
  80. </ele-pro-table>
  81. </el-col>
  82. <el-col :span="3" style="padding: 0">
  83. <div class="el_tree_box">
  84. <div
  85. style="
  86. margin-bottom: 6px;
  87. display: flex;
  88. justify-items: flex-start;
  89. "
  90. >
  91. <el-button
  92. style="width: 50%"
  93. type="primary"
  94. :class="{ current_button: leftTreeActiveName == 'BOM维度' }"
  95. size="small"
  96. plain
  97. @click="handleLeftTreeActiveName('BOM维度')"
  98. >BOM维度
  99. </el-button>
  100. <el-button
  101. style="width: 50%"
  102. type="primary"
  103. :class="{ current_button: leftTreeActiveName == '阶段维度' }"
  104. size="small"
  105. plain
  106. @click="handleLeftTreeActiveName('阶段维度')"
  107. >阶段维度
  108. </el-button>
  109. </div>
  110. <el-input
  111. v-model="filterText"
  112. placeholder="在结构中查找"
  113. size="small"
  114. clearable
  115. style="margin-bottom: 3px"
  116. >
  117. </el-input>
  118. <el-tree
  119. class="project_tree"
  120. ref="treeRef"
  121. :data="treeList"
  122. :default-expanded-keys="
  123. currentNodeData && currentNodeData.id
  124. ? [currentNodeData.id]
  125. : []
  126. "
  127. :expand-on-click-node="false"
  128. :highlight-current="true"
  129. :indent="0"
  130. :props="defaultProps"
  131. node-key="id"
  132. style="height: 100%"
  133. :filter-node-method="filterNode"
  134. @node-click="handleNodeClick"
  135. >
  136. <div
  137. style="width: 100%; height: 100%; display: flex"
  138. slot-scope="{ node, data }"
  139. @contextmenu.stop="(e) => showRightMenu(e, node, data)"
  140. >
  141. <span class="custom-tree-node">
  142. <span
  143. :style="fontSize(node, data)"
  144. class="label_img"
  145. :class="getIconClass(node, data)"
  146. ></span>
  147. <span :style="fontSize(node, data)" class="label">{{
  148. node.label
  149. }}</span>
  150. </span>
  151. <vue-context-menu
  152. :transferIndex="0"
  153. :class="
  154. 'vue-contextmenuName-' +
  155. data.id +
  156. '_' +
  157. data.name +
  158. '_rightMenu'
  159. "
  160. v-if="
  161. data.id + '_' + data.name + '_rightMenu' ==
  162. contextMenuData.menuName
  163. "
  164. :contextMenuData="contextMenuData"
  165. @updateProject="() => handleUpdateProject(node, data, 'edit')"
  166. @removeBom="() => bomRemove(node, data)"
  167. @stageRemove="() => stageRemove(node, data)"
  168. @addBOM="() => addOrEditBOM('add', node, data)"
  169. @editBOM="() => addOrEditBOM('edit', node, data)"
  170. @addChildProject="
  171. () => handleUpdateProject(node, data, 'add')
  172. "
  173. @addStage="() => handleAddStage(node, data, 'add')"
  174. @addPlan="() => handleAddPlan('add', node, data)"
  175. @addTask="() => handleAddTask('add', node, data)"
  176. @handleTermination="
  177. () =>
  178. handleStatus(
  179. projectsTerminationAPI,
  180. '确定终止该项目吗?',
  181. node,
  182. data
  183. )
  184. "
  185. @handlePause="
  186. () =>
  187. handleStatus(
  188. projectsPauseAPI,
  189. '确定暂停该项目吗',
  190. node,
  191. data
  192. )
  193. "
  194. @handleStartup="
  195. () =>
  196. handleStatus(
  197. projectsStartupAPI,
  198. '确定启动该项目吗',
  199. node,
  200. data
  201. )
  202. "
  203. @handleFinish="
  204. () =>
  205. handleStatus(
  206. projectsFinishAPI,
  207. '确定完成该项目吗',
  208. node,
  209. data
  210. )
  211. "
  212. @handleBomTermination="
  213. () =>
  214. handleStatus(
  215. projectsBomTerminationAPI,
  216. '确定终止该BOM吗?',
  217. node,
  218. data
  219. )
  220. "
  221. @handleBomPause="
  222. () =>
  223. handleStatus(
  224. projectsBomPauseAPI,
  225. '确定暂停该BOM吗',
  226. node,
  227. data
  228. )
  229. "
  230. @handleBomStartup="
  231. () =>
  232. handleStatus(
  233. projectsBomStartupAPI,
  234. '确定启动该BOM吗',
  235. node,
  236. data
  237. )
  238. "
  239. @handleBomFinish="
  240. () =>
  241. handleStatus(
  242. projectsBomFinishAPI,
  243. '确定完成该BOM吗',
  244. node,
  245. data
  246. )
  247. "
  248. @handleStageTermination="
  249. () =>
  250. handleStatus(
  251. projectsStageTerminationAPI,
  252. '确定终止该项目阶段吗?',
  253. node,
  254. data
  255. )
  256. "
  257. @handleStagePause="
  258. () =>
  259. handleStatus(
  260. projectsStagePauseAPI,
  261. '确定暂停该项目阶段吗',
  262. node,
  263. data
  264. )
  265. "
  266. @handleStageStartup="
  267. () =>
  268. handleStatus(
  269. projectsStageStartupAPI,
  270. '确定启动该项目阶段吗',
  271. node,
  272. data
  273. )
  274. "
  275. @handleStageFinish="
  276. () =>
  277. handleStatus(
  278. projectsStageFinishAPI,
  279. '确定完成该项目阶段吗',
  280. node,
  281. data
  282. )
  283. "
  284. ></vue-context-menu>
  285. </div>
  286. </el-tree>
  287. </div>
  288. </el-col>
  289. <el-col :span="17">
  290. <ele-split-layout
  291. :left-style="{
  292. overflow: 'hidden',
  293. width: '100%'
  294. }"
  295. :vertical="true"
  296. :max-size="500"
  297. :min-size="1"
  298. :resizable="true"
  299. :responsive="true"
  300. width="450px"
  301. :right-style="{ overflow: 'hidden' }"
  302. allow-collapse
  303. >
  304. <div class="card_2_layout_content">
  305. <el-tabs
  306. v-model="activeName"
  307. class="tab-box_1"
  308. type="border-card"
  309. @tab-click="handleTabs1"
  310. >
  311. <el-tab-pane label="基本信息" name="基本信息">
  312. <div style="padding: 0 10px">
  313. <attribute
  314. v-if="currentNodeData.type == 1"
  315. ref="attributeRef"
  316. :dialog-type="dialogType"
  317. ></attribute>
  318. <project-form
  319. v-if="[0, 2].includes(currentNodeData.type)"
  320. ref="projectForm"
  321. :deptList="deptList"
  322. :deptTreeList="deptTreeList"
  323. :dialogForm="dialogForm"
  324. :teamList="teamList"
  325. dialog-type="view"
  326. ></project-form>
  327. </div>
  328. </el-tab-pane>
  329. <el-tab-pane
  330. v-if="[0, 2].includes(currentNodeData.type)"
  331. label="项目阶段"
  332. name="项目阶段"
  333. class="el-tab-pane-tree"
  334. >
  335. <project-info-table
  336. ref="projectInfoTable"
  337. :dialog-type="dialogType"
  338. :dialogForm="dialogForm"
  339. :deptList="deptList"
  340. :deptTreeList="deptTreeList"
  341. ></project-info-table>
  342. </el-tab-pane>
  343. <el-tab-pane
  344. label="计划"
  345. name="计划"
  346. class="el-tab-pane-tree"
  347. style="overflow: scroll"
  348. >
  349. <div style="padding: 0 10px">
  350. <planManageList
  351. :projectType="currentNodeData.type"
  352. :ids="currentNodeData.id"
  353. @handlePlanTableNodeClick="handlePlanTableNodeClick"
  354. v-if="refreshPlan"
  355. ></planManageList>
  356. <!-- <ele-pro-table
  357. class="el-table"
  358. ref="table"
  359. row-key="id"
  360. :columns="columns"
  361. :datasource="planAndTaskTree"
  362. height="100%"
  363. @row-click="handleTableNodeClick"
  364. @row-contextmenu="showTableRightMenu"
  365. :toolkit="[]"
  366. :default-expand-all="true"
  367. cache-key="project-initiationTable"
  368. :tree-props="{ children: 'children' }"
  369. :need-page="false"
  370. :indent="0"
  371. >
  372. <template v-slot:name="{ row }">
  373. <span
  374. v-if="!row.children.length && row.level == 1"
  375. style="margin-left: 25px; display: inline-block"
  376. ></span>
  377. <span class="dot" v-if="row.milepost == '1'"></span>
  378. <span class="name"> {{ row.name }}</span>
  379. </template>
  380. <template v-slot:type="{ row }">
  381. <el-tag v-if="row.type == 0" type="info">计划</el-tag>
  382. <el-tag v-else-if="row.type == 1" type="info"
  383. >计划节点</el-tag
  384. >
  385. <el-tag v-else-if="row.type == 2" type="info"
  386. >任务</el-tag
  387. >
  388. </template>
  389. <template v-slot:speedPercent="{ row }">
  390. <el-progress
  391. style="padding: 0 5px"
  392. :stroke-width="20"
  393. text-color="#606266"
  394. :text-inside="true"
  395. :percentage="row.speedPercent || 0"
  396. :color="customColorMethod"
  397. ></el-progress>
  398. <vue-context-menu
  399. :transferIndex="0"
  400. :class="'vue-contextmenuName-' + row.name"
  401. v-if="row.name == contextTableMenuData.menuName"
  402. :contextMenuData="contextTableMenuData"
  403. @addPlan="() => handleAddPlan('add', '', row, 'plan')"
  404. @editPlan="
  405. () => handleAddPlan('edit', '', row, 'plan')
  406. "
  407. @removePlan="() => handleRemovePlan([row.id])"
  408. @terminationPlan="
  409. () =>
  410. handleStatus(
  411. planTerminationAPI,
  412. '确定终止该计划吗?',
  413. '',
  414. row
  415. )
  416. "
  417. @pausePlan="
  418. () =>
  419. handleStatus(
  420. planPauseAPI,
  421. '确定暂停该计划吗',
  422. '',
  423. row
  424. )
  425. "
  426. @startupPlan="
  427. () =>
  428. handleStatus(
  429. planStartupAPI,
  430. '确定启动该计划吗',
  431. '',
  432. row
  433. )
  434. "
  435. @finishPlan="
  436. () =>
  437. handleStatus(
  438. planFinishAPI,
  439. '确定完成该计划吗',
  440. '',
  441. row
  442. )
  443. "
  444. @terminationPlanStage="
  445. () =>
  446. handleStatus(
  447. planStageTerminationAPI,
  448. '确定终止该计划节点吗?',
  449. '',
  450. row
  451. )
  452. "
  453. @pausePlanStage="
  454. () =>
  455. handleStatus(
  456. planStagePauseAPI,
  457. '确定暂停该计划节点吗',
  458. '',
  459. row
  460. )
  461. "
  462. @startupPlanStage="
  463. () =>
  464. handleStatus(
  465. planStageStartupAPI,
  466. '确定启动该计划节点吗',
  467. '',
  468. row
  469. )
  470. "
  471. @finishPlanStage="
  472. () =>
  473. handleStatus(
  474. planStageFinishAPI,
  475. '确定完成该计划节点吗',
  476. '',
  477. row
  478. )
  479. "
  480. @addTask="() => handleAddTask('add', '', row, 'plan')"
  481. @updateTask="
  482. () =>
  483. handleAddTask(
  484. 'edit',
  485. '',
  486. { ...row, type: 2 },
  487. 'plan'
  488. )
  489. "
  490. @removeTask="() => handleRemoveTask([row.id])"
  491. @startTask="
  492. () =>
  493. handleStartTask(row, 1, '是否确定执行该任务?')
  494. "
  495. @finishTask="
  496. () =>
  497. handleStartTask(row, 3, '是否确定报工该任务?')
  498. "
  499. @pauseTask="
  500. () =>
  501. handleStartTask(row, 2, '是否确定暂停该任务?')
  502. "
  503. @terminationTask="
  504. () =>
  505. handleStartTask(row, 4, '是否确定终止该任务?')
  506. "
  507. @handleTransfer="() => handleTransfer(row)"
  508. @handleSubmitDeliverables="
  509. () => handleSubmitDeliverables(row)
  510. "
  511. ></vue-context-menu>
  512. </template>
  513. </ele-pro-table> -->
  514. </div>
  515. </el-tab-pane>
  516. <el-tab-pane label="任务" name="任务" class="el-tab-pane-tree">
  517. <ele-pro-table
  518. class="el-table"
  519. ref="table"
  520. row-key="id"
  521. :columns="columns"
  522. :datasource="taskTree"
  523. height="100%"
  524. :max-height="500"
  525. @row-click="
  526. (row) => handleTableNodeClick({ ...row, type: 2 })
  527. "
  528. @row-contextmenu="
  529. (row, column, event) =>
  530. showTableRightMenu({ ...row, type: 2 }, column, event)
  531. "
  532. :toolkit="[]"
  533. :default-expand-all="true"
  534. cache-key="project-initiationTable"
  535. :tree-props="{ children: 'children' }"
  536. :need-page="false"
  537. :indent="0"
  538. >
  539. <template v-slot:name="{ row }">
  540. <span
  541. v-if="!row.children.length && row.level == 1"
  542. style="margin-left: 25px; display: inline-block"
  543. ></span>
  544. <span class="dot" v-if="row.milepost == '1'"></span>
  545. <span class="name"> {{ row.name }}</span>
  546. </template>
  547. <template v-slot:type="{ row }">
  548. <el-tag type="info">任务</el-tag>
  549. </template>
  550. <template v-slot:speedPercent="{ row }">
  551. <el-progress
  552. style="padding: 0 5px"
  553. :stroke-width="20"
  554. text-color="#606266"
  555. :text-inside="true"
  556. :percentage="row.speedPercent || 0"
  557. :color="customColorMethod"
  558. ></el-progress>
  559. <vue-context-menu
  560. :transferIndex="0"
  561. :class="'vue-contextmenuName-' + row.name"
  562. v-if="row.name == contextTableMenuData.menuName"
  563. :contextMenuData="contextTableMenuData"
  564. @addTask="
  565. () =>
  566. handleAddTask(
  567. 'add',
  568. '',
  569. { ...row, type: 2 },
  570. 'plan'
  571. )
  572. "
  573. @updateTask="
  574. () =>
  575. handleAddTask(
  576. 'edit',
  577. '',
  578. { ...row, type: 2 },
  579. 'plan'
  580. )
  581. "
  582. @removeTask="() => handleRemoveTask([row.id])"
  583. @startTask="
  584. () => handleStartTask(row, 1, '是否确定执行该任务?')
  585. "
  586. @finishTask="
  587. () => handleStartTask(row, 3, '是否确定报工该任务?')
  588. "
  589. @pauseTask="
  590. () => handleStartTask(row, 2, '是否确定暂停该任务?')
  591. "
  592. @terminationTask="
  593. () => handleStartTask(row, 4, '是否确定终止该任务?')
  594. "
  595. @handleTransfer="() => handleTransfer(row)"
  596. @handleSubmitDeliverables="
  597. () => handleSubmitDeliverables(row)
  598. "
  599. ></vue-context-menu>
  600. </template>
  601. </ele-pro-table>
  602. </el-tab-pane>
  603. <el-tab-pane
  604. label="项目团队"
  605. name="项目团队"
  606. class="el-tab-pane-tree"
  607. >
  608. <team-info-table
  609. ref="deliverablesInfoTable"
  610. dialog-type="view"
  611. :dialogForm="teamForm"
  612. ></team-info-table>
  613. </el-tab-pane>
  614. <el-tab-pane
  615. label="项目看板"
  616. name="项目看板"
  617. class="el-tab-pane-tree"
  618. >
  619. </el-tab-pane>
  620. <el-tab-pane
  621. label="项目审核流程"
  622. name="项目审核流程"
  623. class="el-tab-pane-tree"
  624. style="overflow: scroll; padding-bottom: 30px"
  625. >
  626. <bpmDetail
  627. v-if="dialogForm.processInstanceId && bpmDetailFlag"
  628. :id="dialogForm.processInstanceId"
  629. ></bpmDetail>
  630. </el-tab-pane>
  631. <el-tab-pane
  632. label="项目行事历"
  633. name="项目行事历"
  634. class="el-tab-pane-tree"
  635. style="overflow: scroll; padding-bottom: 30px"
  636. >
  637. <!-- <projectCalendar></projectCalendar> -->
  638. </el-tab-pane>
  639. </el-tabs>
  640. </div>
  641. <template v-slot:content>
  642. <el-tabs
  643. v-if="isShow"
  644. v-model="attrActiveName"
  645. class="tab-box_2"
  646. type="border-card"
  647. >
  648. <el-tab-pane label="属性" name="属性">
  649. <!--currentTableNodeData-->
  650. <plan-form
  651. ref="planForm"
  652. dialog-type="view"
  653. :dialogForm="rightForm"
  654. :deptList="deptList"
  655. :deptTreeList="deptTreeList"
  656. ></plan-form>
  657. <base-form
  658. ref="baseForm"
  659. v-if="[2].includes(currentTableNodeData.type)"
  660. dialog-type="view"
  661. :dialogForm="rightForm"
  662. :deptList="deptList"
  663. :deptTreeList="deptTreeList"
  664. ></base-form>
  665. </el-tab-pane>
  666. <el-tab-pane label="计划节点" name="计划节点">
  667. <plan-info-table
  668. ref="planInfoTable"
  669. dialog-type="view"
  670. :dialogForm="rightForm"
  671. :deptList="deptList"
  672. :deptTreeList="deptTreeList"
  673. ></plan-info-table>
  674. </el-tab-pane>
  675. <el-tab-pane
  676. v-if="[2].includes(currentTableNodeData.type)"
  677. label="交付物"
  678. name="交付物"
  679. class="el-tab-pane-tree"
  680. >
  681. <submit-deliverables-info-table
  682. ref="deliverablesInfoTable"
  683. :dictList="dictList"
  684. dialog-type="view"
  685. :dialogForm="rightForm"
  686. ></submit-deliverables-info-table>
  687. </el-tab-pane>
  688. </el-tabs>
  689. </template>
  690. </ele-split-layout>
  691. </el-col>
  692. </el-row>
  693. <!-- <div class="card_2_box_content">
  694. <ele-split-layout
  695. :left-style="{
  696. overflow: 'hidden',
  697. width: '100%',
  698. paddingLeft: '10px'
  699. }"
  700. :max-size="300"
  701. :min-size="0"
  702. :resizable="true"
  703. :responsive="true"
  704. :right-style="{ overflow: 'hidden' }"
  705. allow-collapse
  706. width="210px"
  707. >
  708. <template v-slot:content> </template>
  709. </ele-split-layout>
  710. </div> -->
  711. </el-card>
  712. <add-BOM-dialog
  713. v-if="addBOMDialogFlag"
  714. ref="addBOMDialogRef"
  715. :addBOMDialogFlag.sync="addBOMDialogFlag"
  716. :treeList="treeList"
  717. @reload="reload"
  718. ></add-BOM-dialog>
  719. <!-- 新增计划 -->
  720. <add-plan-dialog
  721. v-if="addPlanDialogFLag"
  722. @reload="reload"
  723. :addOrEditDialogFlag.sync="addPlanDialogFLag"
  724. ref="addPlanDialogRef"
  725. ></add-plan-dialog>
  726. <plan-detail-dialog
  727. v-if="planDetailDialogFlag"
  728. :detailDialogFlag.sync="planDetailDialogFlag"
  729. ref="planDetailDialogRef"
  730. ></plan-detail-dialog>
  731. <!-- 编辑弹窗 -->
  732. <add-task-dialog
  733. v-if="addTaskDialogFlag"
  734. @reload="reload"
  735. :addOrEditDialogFlag.sync="addTaskDialogFlag"
  736. ref="addTaskDialogRef"
  737. ></add-task-dialog>
  738. <task-detail-dialog
  739. v-if="taskDetailDialogFlag"
  740. :detailDialogFlag.sync="taskDetailDialogFlag"
  741. ref="taskDetailDialogRef"
  742. ></task-detail-dialog>
  743. <transfer-dialog
  744. ref="transferDialogRef"
  745. v-if="transferDialogFlag"
  746. @reload="reload"
  747. :transferDialogFlag.sync="transferDialogFlag"
  748. ></transfer-dialog>
  749. <submit-deliverables-dialog
  750. ref="submitDeliverablesDialogRef"
  751. v-if="submitDeliverablesDialogFlag"
  752. :submitDeliverablesDialogFlag.sync="submitDeliverablesDialogFlag"
  753. @reload="reload"
  754. ></submit-deliverables-dialog>
  755. <!-- 编辑弹窗 -->
  756. <addOrEditProjectDialog
  757. v-if="addOrEditProjectDialogFlag"
  758. @reload="reload"
  759. :addOrEditDialogFlag.sync="addOrEditProjectDialogFlag"
  760. ref="addOrEditProjectDialogRef"
  761. ></addOrEditProjectDialog>
  762. <!-- 阶段弹窗 -->
  763. <addOrEditStageDialog
  764. v-if="addOrEditDialogStageFlag"
  765. @reload="reload"
  766. :addOrEditDialogStageFlag.sync="addOrEditDialogStageFlag"
  767. ref="addOrEditStageDialogRef"
  768. ></addOrEditStageDialog>
  769. </el-drawer>
  770. </template>
  771. <script>
  772. import p_search from './p_search.vue';
  773. import {
  774. projectsBomDeleteAPI,
  775. projectsBomFinishAPI,
  776. projectsBomPauseAPI,
  777. projectsBomStartupAPI,
  778. projectsBomTerminationAPI
  779. } from '@/api/project-manage/BOM.js';
  780. import Attribute from '@/views/BOMmanage/components/attribute.vue';
  781. import BOMBaseForm from '@/views/BOMmanage/components/BOMBaseForm.vue';
  782. import addBOMDialog from '@/views/BOMmanage/components/addBOMDialog.vue';
  783. import {
  784. projectsPageAPI,
  785. getByBomTreeAPI,
  786. getPlanAndTaskTreeById,
  787. getProjectStageTree,
  788. getTaskTreeById,
  789. projectsFinishAPI,
  790. projectsGetByIdDetailsAPI,
  791. projectsPauseAPI,
  792. projectsStageDeleteAPI,
  793. projectsStageFinishAPI,
  794. projectsStagePauseAPI,
  795. projectsStageStartupAPI,
  796. projectsStageTerminationAPI,
  797. projectsStartupAPI,
  798. projectsTerminationAPI
  799. } from '@/api/project-manage';
  800. import projectForm from '@/views/project-manage/project-initiation/components/project-form.vue';
  801. import { listOrganizations } from '@/api/system/organization';
  802. import {
  803. projectsTeamGetByIdAPI,
  804. projectsTeamPageAPI
  805. } from '@/api/project-manage/team';
  806. import PlanCard from '@/views/BOMmanage/components/planCard.vue';
  807. import addPlanDialog from '@/views/project-manage/planManage/components/addOrEditDialog.vue';
  808. import planDetailDialog from '@/views/project-manage/planManage/components/detailDialog.vue';
  809. import taskDetailDialog from '@/views/project-manage/task-manage/components/detailDialog.vue';
  810. import planForm from '@/views/project-manage/planManage/components/plan-form.vue';
  811. import {
  812. planFinishAPI,
  813. planPauseAPI,
  814. planStageFinishAPI,
  815. planStagePauseAPI,
  816. planStageStartupAPI,
  817. planStageTerminationAPI,
  818. planStartupAPI,
  819. planTerminationAPI,
  820. projectsPlanDeleteAPI,
  821. projectsPlanGetByIdAPI
  822. } from '@/api/project-manage/plan';
  823. import { deepClone } from '@/utils';
  824. import planInfoTable from '@/views/project-manage/planManage/components/planInfoTable.vue';
  825. import BaseForm from '@/views/project-manage/task-manage/components/base-form.vue';
  826. import {
  827. projectsTaskDeleteAPI,
  828. projectsTaskGetByIdAPI,
  829. projectsTaskOpRation
  830. } from '@/api/project-manage/task';
  831. import submitDeliverablesInfoTable from '@/views/project-manage/task-manage/components/submitDeliverablesInfoTable.vue';
  832. import { getByCode } from '@/api/system/dictionary-data';
  833. import teamInfoTable from '@/views/project-manage/team-manage/components/team-Info-table.vue';
  834. import addTaskDialog from '@/views/project-manage/task-manage/components/addOrEditDialog.vue';
  835. import { proStatusEnum, reviewStatusEnum } from '@/enum/dict';
  836. import transferDialog from '@/views/project-manage/task-manage/components/transferDialog.vue';
  837. import submitDeliverablesDialog from '@/views/project-manage/task-manage/components/submitDeliverablesDialog.vue';
  838. import addOrEditProjectDialog from '@/views/project-manage/project-initiation/components/addOrEditDialog.vue';
  839. import bpmDetail from '@/views/bpm/processInstance/detail.vue';
  840. import projectCalendar from '@/views/project-manage/project-calendar/index.vue';
  841. import planManageList from '@/views/project-manage/planManage/index.vue';
  842. import addOrEditStageDialog from '@/views/project-manage/project-initiation/components/addOrEditStageDialog.vue';
  843. import projectInfoTable from '@/views/project-manage/project-initiation/components/projectInfoTable.vue';
  844. export default {
  845. props: {},
  846. components: {
  847. p_search,
  848. bpmDetail,
  849. addOrEditProjectDialog,
  850. submitDeliverablesDialog,
  851. transferDialog,
  852. addTaskDialog,
  853. teamInfoTable,
  854. submitDeliverablesInfoTable,
  855. BaseForm,
  856. planInfoTable,
  857. planForm,
  858. taskDetailDialog,
  859. planDetailDialog,
  860. addPlanDialog,
  861. PlanCard,
  862. projectForm,
  863. BOMBaseForm,
  864. Attribute,
  865. addBOMDialog,
  866. planManageList,
  867. projectCalendar,
  868. projectInfoTable,
  869. addOrEditStageDialog
  870. },
  871. data() {
  872. return {
  873. visible: false,
  874. title: '项目信息',
  875. projectsFinishAPI,
  876. projectsPauseAPI,
  877. projectsStartupAPI,
  878. projectsTerminationAPI,
  879. projectsBomFinishAPI,
  880. projectsBomPauseAPI,
  881. projectsBomStartupAPI,
  882. projectsBomTerminationAPI,
  883. projectsStageFinishAPI,
  884. projectsStagePauseAPI,
  885. projectsStageStartupAPI,
  886. projectsStageTerminationAPI,
  887. planFinishAPI,
  888. planPauseAPI,
  889. planStartupAPI,
  890. planTerminationAPI,
  891. planStageFinishAPI,
  892. planStagePauseAPI,
  893. planStageStartupAPI,
  894. planStageTerminationAPI,
  895. activeName: '基本信息',
  896. attrActiveName: '属性',
  897. leftTreeActiveName: 'BOM维度',
  898. active: 0,
  899. contextMenuData: {
  900. menuName: '',
  901. axis: {
  902. x: null,
  903. y: null
  904. }, // 鼠标位置
  905. menulists: []
  906. },
  907. contextTableMenuData: {
  908. menuName: '',
  909. axis: {
  910. x: null,
  911. y: null
  912. }, // 鼠标位置
  913. menulists: []
  914. },
  915. currentNodeData: {},
  916. planAndTaskTree: [],
  917. taskTree: [],
  918. deptList: [],
  919. deptTreeList: [],
  920. projectStepList: ['待立项', '审核中', '执行中', '已完成'],
  921. teamList: [],
  922. current: {},
  923. dialogForm: {},
  924. rightForm: {},
  925. teamForm: {},
  926. dictList: {},
  927. currentTableNodeData: {},
  928. treeList: [],
  929. addOrEditDialogStageFlag: false,
  930. bpmDetailFlag: false,
  931. isShow: false,
  932. treeLoading: false,
  933. addBOMDialogFlag: false,
  934. addPlanDialogFLag: false,
  935. addTaskDialogFlag: false,
  936. planDetailDialogFlag: false,
  937. taskDetailDialogFlag: false,
  938. transferDialogFlag: false,
  939. submitDeliverablesDialogFlag: false,
  940. addOrEditProjectDialogFlag: false,
  941. defaultProps: {
  942. children: 'children',
  943. label: 'name'
  944. },
  945. loading: false,
  946. filterText: null,
  947. categoryId: 1,
  948. loadingInstance: null,
  949. treeId: null,
  950. dialogType: null,
  951. columnsLeft: [
  952. /* {
  953. columnKey: 'index',
  954. label: '序号',
  955. type: 'index',
  956. width: 55,
  957. align: 'center',
  958. showOverflowTooltip: true
  959. }, */
  960. {
  961. prop: 'code',
  962. label: '项目编码',
  963. showOverflowTooltip: true,
  964. minWidth: 160,
  965. slot: 'code',
  966. align: 'center'
  967. },
  968. {
  969. prop: 'name',
  970. label: '项目名称',
  971. align: 'center',
  972. showOverflowTooltip: true,
  973. minWidth: 140
  974. }
  975. ],
  976. leftTreeData: [],
  977. rowData: {},
  978. refreshPlan: true
  979. };
  980. },
  981. watch: {
  982. filterText(val) {
  983. this.$refs.treeRef.filter(val);
  984. }
  985. },
  986. computed: {
  987. columns() {
  988. return [
  989. {
  990. columnKey: 'index',
  991. label: '序号',
  992. type: 'index',
  993. width: 55,
  994. align: 'center',
  995. showOverflowTooltip: true
  996. },
  997. {
  998. label: '名称',
  999. prop: 'name',
  1000. showOverflowTooltip: true,
  1001. minWidth: 180,
  1002. slot: 'name'
  1003. },
  1004. {
  1005. label: '类型名称',
  1006. prop: 'type',
  1007. showOverflowTooltip: true,
  1008. minWidth: 80,
  1009. align: 'center',
  1010. slot: 'type'
  1011. },
  1012. {
  1013. label: '预计开始时间',
  1014. prop: 'planStartDate',
  1015. formatter: (val) => {
  1016. return val.planStartDate?.split(' ')[0];
  1017. },
  1018. showOverflowTooltip: true,
  1019. minWidth: 150,
  1020. align: 'center'
  1021. },
  1022. {
  1023. label: '预计结束时间',
  1024. prop: 'planEndDate',
  1025. formatter: (val) => {
  1026. return val.planEndDate?.split(' ')[0];
  1027. },
  1028. showOverflowTooltip: true,
  1029. minWidth: 150,
  1030. align: 'center'
  1031. },
  1032. {
  1033. label: '预计工期(天)',
  1034. prop: 'planDay',
  1035. showOverflowTooltip: true,
  1036. minWidth: 150,
  1037. align: 'center'
  1038. },
  1039. {
  1040. label: '实际开始时间',
  1041. prop: 'realStartTime',
  1042. // formatter: (val) => {
  1043. // return val.realStartTime?.split(' ')[0]
  1044. // },
  1045. showOverflowTooltip: true,
  1046. minWidth: 150,
  1047. align: 'center'
  1048. },
  1049. {
  1050. label: '实际结束时间',
  1051. prop: 'realEndTime',
  1052. // formatter: (val) => {
  1053. // return val.realEndTime?.split(' ')[0]
  1054. // },
  1055. showOverflowTooltip: true,
  1056. minWidth: 150,
  1057. align: 'center'
  1058. },
  1059. {
  1060. label: '实际工期(天)',
  1061. prop: 'realDay',
  1062. showOverflowTooltip: true,
  1063. minWidth: 150,
  1064. align: 'center'
  1065. },
  1066. {
  1067. label: '负责人',
  1068. prop: 'responsibleUserName',
  1069. showOverflowTooltip: true,
  1070. minWidth: 100,
  1071. align: 'center'
  1072. },
  1073. {
  1074. prop: 'processStatus',
  1075. label: '审核状态',
  1076. align: 'center',
  1077. showOverflowTooltip: true,
  1078. minWidth: 100,
  1079. formatter: (_row, _column, cellValue) => {
  1080. return reviewStatusEnum[_row.processStatus]?.label;
  1081. }
  1082. },
  1083. {
  1084. prop: 'status',
  1085. label: '状态',
  1086. align: 'center',
  1087. showOverflowTooltip: true,
  1088. minWidth: 100,
  1089. formatter: (_row, _column, cellValue) => {
  1090. return proStatusEnum[_row.status]?.label;
  1091. }
  1092. },
  1093. {
  1094. label: '进度',
  1095. prop: 'speedPercent',
  1096. showOverflowTooltip: false,
  1097. minWidth: 120,
  1098. align: 'center',
  1099. slot: 'speedPercent'
  1100. }
  1101. ];
  1102. }
  1103. },
  1104. mounted() {
  1105. this.leftTreeActiveName = 'BOM维度';
  1106. this.activeName = '基本信息';
  1107. this.attrActiveName = '属性';
  1108. this.isShow = false;
  1109. /* if (this.$route.query.id) {
  1110. this.initData();
  1111. this.dialogType = this.$route.query.type;
  1112. } */
  1113. this.getDeptList();
  1114. this.getTeamList();
  1115. this.getDictList('pro_files_approve_type');
  1116. this.getDictList('deliverables_type');
  1117. this.getDictList('pro_projects_status');
  1118. this.getDictList('pro_projects_budget_unit');
  1119. },
  1120. /* activated() {
  1121. if (this.$route.query.id) {
  1122. this.initData();
  1123. this.dialogType = this.$route.query.type;
  1124. }
  1125. }, */
  1126. methods: {
  1127. getDictV(code, val) {
  1128. if (!this.dictList[code]) return '';
  1129. return this.dictList[code].find((item) => item.value == val)?.label;
  1130. },
  1131. async getDictList(code) {
  1132. let { data: res } = await getByCode(code);
  1133. this.dictList[code] = res.map((item) => {
  1134. let values = Object.keys(item);
  1135. return {
  1136. value: values[0],
  1137. label: item[values[0]]
  1138. };
  1139. });
  1140. },
  1141. async open(row) {
  1142. this.rowData = row;
  1143. this.visible = true;
  1144. if (this.rowData.id) {
  1145. this.initData();
  1146. this.dialogType = this.rowData.type;
  1147. }
  1148. this.getLeftData();
  1149. },
  1150. async getLeftData(where) {
  1151. let pp = {
  1152. pageNum: 1,
  1153. size: 999,
  1154. parentId: parent?.id ?? '0',
  1155. /* name: this.rowData.name ?? '', */
  1156. ...where
  1157. };
  1158. const res = await projectsPageAPI(pp);
  1159. this.leftTreeData = res.list;
  1160. },
  1161. cancel() {
  1162. this.$nextTick(() => {
  1163. this.visible = false;
  1164. });
  1165. },
  1166. handleTabs1(val) {
  1167. this.activeName = val.label;
  1168. this.attrActiveName = '属性';
  1169. this.isShow = false;
  1170. this.bpmDetailFlag = false;
  1171. this.$nextTick(() => {
  1172. this.bpmDetailFlag = true;
  1173. });
  1174. },
  1175. filterNode(value, data) {
  1176. if (!value) return true;
  1177. return data.name.indexOf(value) !== -1;
  1178. },
  1179. async getDictList(code) {
  1180. let { data: res } = await getByCode(code);
  1181. this.dictList[code] = res.map((item) => {
  1182. let values = Object.keys(item);
  1183. return {
  1184. value: values[0],
  1185. label: item[values[0]]
  1186. };
  1187. });
  1188. },
  1189. initData() {
  1190. this.getTreeData();
  1191. },
  1192. // 获取部门数据
  1193. getDeptList() {
  1194. listOrganizations().then((list) => {
  1195. this.deptList = list;
  1196. this.deptTreeList = this.$util.toTreeData({
  1197. data: list,
  1198. idField: 'id',
  1199. parentIdField: 'parentId'
  1200. });
  1201. console.log(this.deptTreeList);
  1202. });
  1203. },
  1204. getTeamList() {
  1205. projectsTeamPageAPI({
  1206. pageNum: 1,
  1207. size: 999
  1208. }).then((list) => {
  1209. this.teamList = list;
  1210. });
  1211. },
  1212. handleUpdateProject(node, data, type) {
  1213. this.addOrEditProjectDialogFlag = true;
  1214. this.$nextTick(() => {
  1215. this.$refs.addOrEditProjectDialogRef.init(data, type);
  1216. });
  1217. },
  1218. bomRemove(node, data) {
  1219. let message = data.children.length
  1220. ? '当前节点包含子节点,是否确认删除?'
  1221. : '是否确认删除?';
  1222. this.$confirm(message, '提示', {
  1223. confirmButtonText: '确定',
  1224. cancelButtonText: '取消',
  1225. type: 'warning'
  1226. })
  1227. .then(async () => {
  1228. const loading = this.$loading({ lock: true });
  1229. await projectsBomDeleteAPI([data.id]);
  1230. loading.close();
  1231. this.$message.success('删除成功');
  1232. await this.getTreeData();
  1233. })
  1234. .catch(() => {
  1235. this.$message({
  1236. type: 'info',
  1237. message: '已取消删除'
  1238. });
  1239. });
  1240. },
  1241. stageRemove(node, data) {
  1242. let message = data.children.length
  1243. ? '当前节点包含子节点,是否确认删除?'
  1244. : '是否确认删除?';
  1245. this.$confirm(message, '提示', {
  1246. confirmButtonText: '确定',
  1247. cancelButtonText: '取消',
  1248. type: 'warning'
  1249. })
  1250. .then(async () => {
  1251. const loading = this.$loading({ lock: true });
  1252. await projectsStageDeleteAPI([data.id]);
  1253. loading.close();
  1254. this.$message.success('删除成功');
  1255. await this.getTreeData();
  1256. })
  1257. .catch(() => {
  1258. this.$message({
  1259. type: 'info',
  1260. message: '已取消删除'
  1261. });
  1262. });
  1263. },
  1264. back() {
  1265. this.$router.go(-1);
  1266. },
  1267. async validateForm() {
  1268. return Promise.all([
  1269. new Promise((resolve, reject) => {
  1270. this.$refs.BOMBaseFormRef.getValidaValue((valid) => {
  1271. if (!valid) {
  1272. reject(false);
  1273. } else {
  1274. resolve(true);
  1275. }
  1276. });
  1277. })
  1278. ]).catch(() => {
  1279. this.$message.warning('请先填写完整信息');
  1280. return Promise.reject(false);
  1281. });
  1282. },
  1283. addChildProject() {},
  1284. addOrEditBOM(type, node, data) {
  1285. this.addBOMDialogFlag = true;
  1286. this.$nextTick(() => {
  1287. this.$refs.addBOMDialogRef.init(data, type);
  1288. });
  1289. },
  1290. handleAddStage(node, data, type) {
  1291. this.addOrEditDialogStageFlag = true;
  1292. this.$nextTick(() => {
  1293. this.$refs.addOrEditStageDialogRef.init(data, type);
  1294. });
  1295. },
  1296. handleAddPlan(type, node, data, sourceName = 'project') {
  1297. this.addPlanDialogFLag = true;
  1298. let params = {};
  1299. if (sourceName == 'plan') {
  1300. params = {
  1301. projectId: data.projectId,
  1302. projectStageId: data.projectStageId,
  1303. projectBomId: data.projectBomId,
  1304. parentPlanId: data.id,
  1305. id: data.id
  1306. };
  1307. } else {
  1308. switch (data.type) {
  1309. case 0:
  1310. params = {
  1311. projectId: data.id
  1312. };
  1313. break;
  1314. case 1:
  1315. params = {
  1316. projectId: data.projectId,
  1317. projectBomId: data.id
  1318. };
  1319. break;
  1320. case 2:
  1321. params = {
  1322. projectId: data.projectId,
  1323. projectStageId: data.id
  1324. };
  1325. break;
  1326. }
  1327. }
  1328. this.$nextTick(() => {
  1329. this.$refs.addPlanDialogRef.init(params, type);
  1330. this.$refs.refreshPlan.datasource();
  1331. });
  1332. },
  1333. async handleStatus(API, msg, node, row) {
  1334. this.$confirm(msg, '提示', {
  1335. type: 'warning'
  1336. })
  1337. .then(async () => {
  1338. await API(row.id);
  1339. this.$message.success('操作成功');
  1340. this.reload();
  1341. })
  1342. .catch(() => {});
  1343. },
  1344. //报工/执行
  1345. async handleStartTask(row, afterStatus, msg) {
  1346. this.$confirm(msg, '提示', {
  1347. confirmButtonText: '确定',
  1348. cancelButtonText: '取消',
  1349. type: 'warning'
  1350. })
  1351. .then(async () => {
  1352. let params = {
  1353. id: row.id,
  1354. afterStatus: afterStatus,
  1355. status: row.status
  1356. };
  1357. await projectsTaskOpRation(params);
  1358. this.$message.success('操作成功');
  1359. this.reload();
  1360. })
  1361. .catch(() => {});
  1362. },
  1363. handleRemovePlan(ids) {
  1364. this.$confirm('此操作将永久删除该计划, 是否继续?', '提示', {
  1365. confirmButtonText: '确定',
  1366. cancelButtonText: '取消',
  1367. type: 'warning'
  1368. }).then(async () => {
  1369. const loading = this.$loading({ lock: true });
  1370. projectsPlanDeleteAPI(ids)
  1371. .then((res) => {
  1372. loading.close();
  1373. this.$message.success('删除成功');
  1374. this.reload();
  1375. })
  1376. .catch((e) => {
  1377. loading.close();
  1378. // this.$message.error(e.message);
  1379. });
  1380. });
  1381. },
  1382. /* 删除 */
  1383. handleRemoveTask(ids) {
  1384. this.$confirm('此操作将永久删除该任务, 是否继续?', '提示', {
  1385. confirmButtonText: '确定',
  1386. cancelButtonText: '取消',
  1387. type: 'warning'
  1388. })
  1389. .then(async () => {
  1390. const loading = this.$loading({ lock: true });
  1391. projectsTaskDeleteAPI(ids)
  1392. .then((res) => {
  1393. loading.close();
  1394. this.$message.success('删除成功');
  1395. this.reload();
  1396. })
  1397. .catch((e) => {
  1398. loading.close();
  1399. // this.$message.error(e.message);
  1400. });
  1401. })
  1402. .catch(() => {});
  1403. },
  1404. /* */
  1405. handleAddTask(type, node, data, sourceName = 'project') {
  1406. this.addTaskDialogFlag = true;
  1407. let params = {};
  1408. if (sourceName == 'plan') {
  1409. switch (data.type) {
  1410. case 0:
  1411. params = {
  1412. targetPlanId: data.id,
  1413. projectId: data.projectId,
  1414. projectStageId: data.projectStageId
  1415. };
  1416. break;
  1417. case 1:
  1418. params = {
  1419. targetPlanId: data.parentId,
  1420. projectId: data.projectId,
  1421. projectStageId: data.projectStageId,
  1422. planStageId: data.id
  1423. };
  1424. break;
  1425. case 2:
  1426. params = {
  1427. targetPlanId: data.targetPlanId,
  1428. projectId: data.projectId,
  1429. projectStageId: data.projectStageId,
  1430. planStageId: data.planStageId,
  1431. taskId: data.id,
  1432. id: type !== 'add' ? data.id : ''
  1433. };
  1434. break;
  1435. }
  1436. } else {
  1437. switch (data.type) {
  1438. case 0:
  1439. params = {
  1440. projectId: data.id
  1441. };
  1442. break;
  1443. case 1:
  1444. params = {
  1445. projectId: data.projectId,
  1446. projectBomId: data.id
  1447. };
  1448. break;
  1449. case 2:
  1450. params = {
  1451. projectId: data.projectId,
  1452. projectStageId: data.id
  1453. };
  1454. break;
  1455. }
  1456. }
  1457. this.$nextTick(() => {
  1458. this.$refs.addTaskDialogRef.init(params, type);
  1459. });
  1460. },
  1461. async getTreeData() {
  1462. try {
  1463. this.treeLoading = true;
  1464. let API =
  1465. this.leftTreeActiveName == 'BOM维度'
  1466. ? getByBomTreeAPI
  1467. : getProjectStageTree;
  1468. const res = await API(this.rowData.id);
  1469. this.treeList = [res];
  1470. this.$nextTick(() => {
  1471. if (this.treeList.length) {
  1472. // 默认高亮第一个
  1473. this.$refs.treeRef.setCurrentKey(this.treeList[0]?.id);
  1474. this.handleNodeClick(this.treeList[0]);
  1475. }
  1476. });
  1477. } catch (error) {}
  1478. this.treeLoading = false;
  1479. },
  1480. getIconClass(node, data) {
  1481. switch (data.type) {
  1482. case 2:
  1483. return node.expanded ? 'el-icon-document' : 'el-icon-tickets';
  1484. case 1:
  1485. return node.expanded ? 'el-icon-document' : 'el-icon-tickets';
  1486. case 0:
  1487. return node.expanded ? 'el-icon-folder-opened' : 'el-icon-folder';
  1488. default:
  1489. return '';
  1490. }
  1491. },
  1492. showRightMenu(event, node, data) {
  1493. if (this.dialogType == 'view') return;
  1494. this.contextMenuData.menuName =
  1495. data.id + '_' + data.name + '_rightMenu';
  1496. this.$nextTick(() => {
  1497. let menuList = [
  1498. ...document.querySelectorAll('.vue-contextmenu-listWrapper')
  1499. ];
  1500. menuList.forEach((item) => {
  1501. item.style.display = 'none';
  1502. });
  1503. event.preventDefault();
  1504. const x = event.clientX;
  1505. const y = event.clientY;
  1506. this.contextMenuData.axis = { x, y };
  1507. switch (data.type) {
  1508. case 0:
  1509. this.contextMenuData.menulists = [
  1510. {
  1511. fnHandler: 'addChildProject',
  1512. icoName: 'fa el-icon-plus',
  1513. btnName: '新建子项目',
  1514. disabled:
  1515. this.disableToAddBOM(data) &&
  1516. this.$hasPermission('pro:projects:save')
  1517. },
  1518. {
  1519. fnHandler: 'addStage',
  1520. icoName: 'fa el-icon-plus',
  1521. btnName: '新建阶段',
  1522. disabled:
  1523. this.disableToAddBOM(data) &&
  1524. this.$hasPermission('pro:projects:save')
  1525. },
  1526. {
  1527. fnHandler: 'addBOM',
  1528. icoName: 'fa el-icon-plus',
  1529. btnName: '新建BOM',
  1530. disabled:
  1531. this.disableToAddBOM(data) &&
  1532. this.$hasPermission('pro:projects:save')
  1533. },
  1534. {
  1535. fnHandler: 'addPlan',
  1536. icoName: 'fa el-icon-plus',
  1537. btnName: '新建计划',
  1538. disabled: this.disableToAddPlan(data)
  1539. },
  1540. {
  1541. fnHandler: 'addTask',
  1542. icoName: 'fa el-icon-plus',
  1543. btnName: '新建任务',
  1544. disabled: this.disableToAddTask(data)
  1545. },
  1546. {
  1547. fnHandler: 'updateProject',
  1548. icoName: 'fa el-icon-edit',
  1549. btnName: '修改',
  1550. disabled:
  1551. [1, 2].includes(data.processStatus) &&
  1552. this.$hasPermission('pro:projects:update')
  1553. },
  1554. {
  1555. fnHandler: 'onRemove',
  1556. icoName: 'fa el-icon-delete',
  1557. btnName: '删除',
  1558. disabled:
  1559. [1, 2].includes(data.processStatus) &&
  1560. this.$hasPermission('pro:projects:delete')
  1561. },
  1562. {
  1563. fnHandler: 'handleFinish',
  1564. icoName: 'fa el-icon-success',
  1565. btnName: '完成',
  1566. disabled:
  1567. this.disableToFinish(data) &&
  1568. this.$hasPermission('pro:projects:update')
  1569. },
  1570. {
  1571. fnHandler: 'handlePause',
  1572. icoName: 'fa el-icon-video-pause',
  1573. btnName: '暂停',
  1574. disabled:
  1575. this.disableToPause(data) &&
  1576. this.$hasPermission('pro:projects:update')
  1577. },
  1578. {
  1579. fnHandler: 'handleStartup',
  1580. icoName: 'fa el-icon-video-play',
  1581. btnName: '启动',
  1582. disabled:
  1583. this.disableToStartup(data) &&
  1584. this.$hasPermission('pro:projects:update')
  1585. },
  1586. {
  1587. fnHandler: 'handleTermination',
  1588. icoName: 'fa el-icon-error',
  1589. btnName: '终止',
  1590. disabled:
  1591. this.disableToTermination(data) &&
  1592. this.$hasPermission('pro:projects:update')
  1593. }
  1594. ];
  1595. break;
  1596. case 1:
  1597. this.contextMenuData.menulists = [
  1598. {
  1599. fnHandler: 'addBOM',
  1600. icoName: 'fa el-icon-plus',
  1601. btnName: '新建BOM',
  1602. disabled:
  1603. this.disableToAddBOM(data) &&
  1604. this.$hasPermission('pro:projects:save')
  1605. },
  1606. {
  1607. fnHandler: 'addPlan',
  1608. icoName: 'fa el-icon-plus',
  1609. btnName: '新建计划',
  1610. disabled: this.disableToAddPlan(data)
  1611. },
  1612. {
  1613. fnHandler: 'addTask',
  1614. icoName: 'fa el-icon-plus',
  1615. btnName: '新建任务',
  1616. disabled: this.disableToAddTask(data)
  1617. },
  1618. {
  1619. fnHandler: 'editBOM',
  1620. icoName: 'fa el-icon-edit',
  1621. btnName: '修改',
  1622. disabled:
  1623. ![0].includes(data.status) &&
  1624. this.$hasPermission('pro:projects:update')
  1625. },
  1626. {
  1627. fnHandler: 'removeBom',
  1628. icoName: 'fa el-icon-delete',
  1629. btnName: '删除',
  1630. disabled:
  1631. ![0].includes(data.status) &&
  1632. this.$hasPermission('pro:projects:delete')
  1633. },
  1634. {
  1635. fnHandler: 'handleBomFinish',
  1636. icoName: 'fa el-icon-success',
  1637. btnName: '完成',
  1638. disabled:
  1639. this.disableToFinish(data) &&
  1640. this.$hasPermission('pro:projects:update')
  1641. },
  1642. {
  1643. fnHandler: 'handleBomPause',
  1644. icoName: 'fa el-icon-video-pause',
  1645. btnName: '暂停',
  1646. disabled:
  1647. this.disableToPause(data) &&
  1648. this.$hasPermission('pro:projects:update')
  1649. },
  1650. {
  1651. fnHandler: 'handleBomStartup',
  1652. icoName: 'fa el-icon-video-play',
  1653. btnName: '启动',
  1654. disabled:
  1655. this.disableToStartup(data) &&
  1656. this.$hasPermission('pro:projects:update')
  1657. },
  1658. {
  1659. fnHandler: 'handleBomTermination',
  1660. icoName: 'fa el-icon-error',
  1661. btnName: '终止',
  1662. disabled:
  1663. this.disableToTermination(data) &&
  1664. this.$hasPermission('pro:projects:update')
  1665. }
  1666. ];
  1667. break;
  1668. case 2:
  1669. this.contextMenuData.menulists = [
  1670. {
  1671. fnHandler: 'addPlan',
  1672. icoName: 'fa el-icon-plus',
  1673. btnName: '新建计划',
  1674. disabled: this.disableToAddPlan(data)
  1675. },
  1676. {
  1677. fnHandler: 'addTask',
  1678. icoName: 'fa el-icon-plus',
  1679. btnName: '新建任务',
  1680. disabled: this.disableToAddTask(data)
  1681. },
  1682. // {fnHandler: 'onSave',
  1683. // icoName: 'fa el-icon-edit',
  1684. // btnName: '修改'
  1685. // },
  1686. // {fnHandler: 'stageRemove',
  1687. // icoName: 'fa el-icon-delete',
  1688. // btnName: '删除'
  1689. // },
  1690. {
  1691. fnHandler: 'handleStageFinish',
  1692. icoName: 'fa el-icon-success',
  1693. btnName: '完成',
  1694. disabled: this.disableToFinish(data)
  1695. },
  1696. {
  1697. fnHandler: 'handleStagePause',
  1698. icoName: 'fa el-icon-video-pause',
  1699. btnName: '暂停',
  1700. disabled: this.disableToPause(data)
  1701. },
  1702. {
  1703. fnHandler: 'handleStageStartup',
  1704. icoName: 'fa el-icon-video-play',
  1705. btnName: '启动',
  1706. disabled: this.disableToStartup(data)
  1707. },
  1708. {
  1709. fnHandler: 'handleStageTermination',
  1710. icoName: 'fa el-icon-error',
  1711. btnName: '终止',
  1712. disabled: this.disableToTermination(data)
  1713. }
  1714. ];
  1715. break;
  1716. }
  1717. });
  1718. },
  1719. disableToAddBOM(row) {
  1720. return (
  1721. ![0, 1, 2, 3].includes(row.processStatus) ||
  1722. ![0, 1].includes(row.status)
  1723. );
  1724. },
  1725. disableToAddPlan(row) {
  1726. return (
  1727. ![0, 1, 2, 3].includes(row.processStatus) ||
  1728. ![0, 1].includes(row.status)
  1729. );
  1730. },
  1731. disableToAddTask(row) {
  1732. return (
  1733. ![0, 1, 2, 3].includes(row.processStatus) ||
  1734. ![0, 1].includes(row.status)
  1735. );
  1736. },
  1737. disableToFinish(row) {
  1738. return (
  1739. ![2].includes(row.processStatus) || [4, 2, 3].includes(row.status)
  1740. );
  1741. },
  1742. disableToPause(row) {
  1743. return (
  1744. ![2].includes(row.processStatus) || [4, 2, 3].includes(row.status)
  1745. );
  1746. },
  1747. disableToStartup(row) {
  1748. return (
  1749. ![2].includes(row.processStatus) || [4, 1, 0, 3].includes(row.status)
  1750. );
  1751. },
  1752. disableToTermination(row) {
  1753. return ![2].includes(row.processStatus) || [4, 3].includes(row.status);
  1754. },
  1755. handleNodeClick(data) {
  1756. this.treeId = data.id;
  1757. this.currentNodeData = data;
  1758. this.$nextTick(async () => {
  1759. switch (data.type) {
  1760. case 1:
  1761. await this.$refs.attributeRef.setAttributeFormData(
  1762. this.currentNodeData
  1763. );
  1764. break;
  1765. case 2:
  1766. this.dialogForm = await projectsGetByIdDetailsAPI(data.parentId);
  1767. break;
  1768. case 0:
  1769. this.dialogForm = await projectsGetByIdDetailsAPI(data.id);
  1770. this.dialogForm.type = this.dialogForm.type + '';
  1771. this.dialogForm.level = this.dialogForm.level + '';
  1772. this.dialogForm.parentId =
  1773. this.dialogForm.parentId == 0 ? '' : this.dialogForm.parentId;
  1774. this.projectStepList = ['待立项', '审核中', '执行中', '已完成'];
  1775. if (data.processStatus == 0) {
  1776. this.active = 0;
  1777. break;
  1778. }
  1779. if ([1, 3].includes(data.processStatus)) {
  1780. let stepName =
  1781. data.processStatus == 3 ? '审核未通过' : '审核中';
  1782. this.projectStepList.splice(1, 1, stepName);
  1783. this.active = 1;
  1784. break;
  1785. }
  1786. if ([0, 1, 2].includes(data.status)) {
  1787. let stepName =
  1788. data.status == 1
  1789. ? '执行中'
  1790. : data.status == 2
  1791. ? '暂停中'
  1792. : '未开始';
  1793. this.projectStepList.splice(2, 1, stepName);
  1794. this.active = 2;
  1795. break;
  1796. }
  1797. if ([3, 4].includes(data.status)) {
  1798. let stepName = data.status == 3 ? '已完成' : '已终止';
  1799. this.projectStepList.splice(3, 1, stepName);
  1800. this.active = 4;
  1801. break;
  1802. }
  1803. break;
  1804. }
  1805. if ([0, 2].includes(data.type)) {
  1806. this.dialogForm.type = this.dialogForm.type + '';
  1807. this.dialogForm.level = this.dialogForm.level + '';
  1808. this.dialogForm.parentId =
  1809. this.dialogForm.parentId == 0 ? '' : this.dialogForm.parentId;
  1810. this.dialogForm.stageList = this.dialogForm.allStageList;
  1811. await this.getTeamInfo(this.dialogForm.teamId);
  1812. }
  1813. });
  1814. this.getPlanAndTaskTree(data);
  1815. this.getTaskTree(data);
  1816. },
  1817. async getPlanAndTaskTree(data) {
  1818. let paramAttr = '';
  1819. switch (data.type) {
  1820. case 1:
  1821. paramAttr = 'projectBomId';
  1822. break;
  1823. case 2:
  1824. paramAttr = 'projectStageId';
  1825. break;
  1826. default:
  1827. paramAttr = 'projectId';
  1828. }
  1829. let params = {
  1830. [paramAttr]: data.id
  1831. };
  1832. this.planAndTaskTree = await getPlanAndTaskTreeById(params);
  1833. },
  1834. async getTaskTree(data) {
  1835. let paramAttr = '';
  1836. switch (data.type) {
  1837. case 1:
  1838. paramAttr = 'projectBomId';
  1839. break;
  1840. case 2:
  1841. paramAttr = 'projectStageId';
  1842. break;
  1843. default:
  1844. paramAttr = 'projectId';
  1845. }
  1846. let params = {
  1847. [paramAttr]: data.id
  1848. };
  1849. this.taskTree = await getTaskTreeById(params);
  1850. },
  1851. reload(where) {
  1852. this.getTreeData();
  1853. },
  1854. setTableCell({ row }) {
  1855. console.log(row.level);
  1856. if (row.level === 1) return ''; //
  1857. return { marginLeft: row.level + 3 + 'px' }; //
  1858. },
  1859. handleTableNodeClick(row) {
  1860. this.isShow = true;
  1861. this.attrActiveName = '属性';
  1862. this.currentTableNodeData = row;
  1863. console.log(row, 'row.type');
  1864. switch (row.type) {
  1865. case 0:
  1866. this.getProjectPlanInfo(row.id);
  1867. break;
  1868. case 1:
  1869. this.getProjectPlanInfo(row.targetPlanId);
  1870. break;
  1871. case 2:
  1872. this.getProjectTaskInfo(row.id);
  1873. break;
  1874. }
  1875. },
  1876. handlePlanTableNodeClick(row) {
  1877. console.log(row, '点击计划某一行');
  1878. this.isShow = true;
  1879. this.attrActiveName = '属性';
  1880. this.currentTableNodeData = row;
  1881. this.getProjectPlanInfo(row.id);
  1882. },
  1883. showTableRightMenu(row, column, event) {
  1884. if (this.dialogType == 'view') return;
  1885. this.contextTableMenuData.menuName = row.name;
  1886. this.$nextTick(() => {
  1887. let menuList = [
  1888. ...document.querySelectorAll('.vue-contextmenu-listWrapper')
  1889. ];
  1890. menuList.forEach((item) => {
  1891. item.style.display = 'none';
  1892. });
  1893. event.preventDefault();
  1894. const x = event.clientX;
  1895. const y = event.clientY;
  1896. this.contextTableMenuData.axis = { x, y };
  1897. switch (row.type) {
  1898. case 0:
  1899. this.contextTableMenuData.menulists = [
  1900. {
  1901. fnHandler: 'addPlan',
  1902. icoName: 'fa el-icon-plus',
  1903. btnName: '新建计划',
  1904. disabled: this.disableToAddPlan(row)
  1905. },
  1906. {
  1907. fnHandler: 'addTask',
  1908. icoName: 'fa el-icon-plus',
  1909. btnName: '新建任务',
  1910. disabled: this.disableToAddTask(row)
  1911. },
  1912. {
  1913. fnHandler: 'editPlan',
  1914. icoName: 'fa el-icon-edit',
  1915. btnName: '修改',
  1916. disabled:
  1917. [1, 2].includes(row.processStatus) ||
  1918. ![0].includes(row.status)
  1919. },
  1920. {
  1921. fnHandler: 'removePlan',
  1922. icoName: 'fa el-icon-delete',
  1923. btnName: '删除',
  1924. disabled:
  1925. [1, 2].includes(row.processStatus) ||
  1926. ![0].includes(row.status)
  1927. },
  1928. {
  1929. fnHandler: 'finishPlan',
  1930. icoName: 'fa el-icon-success',
  1931. btnName: '完成',
  1932. disabled: this.disableToFinish(row)
  1933. },
  1934. {
  1935. fnHandler: 'pausePlan',
  1936. icoName: 'fa el-icon-video-pause',
  1937. btnName: '暂停',
  1938. disabled: this.disableToPause(row)
  1939. },
  1940. {
  1941. fnHandler: 'startupPlan',
  1942. icoName: 'fa el-icon-video-play',
  1943. btnName: '启动',
  1944. disabled: this.disableToStartup(row)
  1945. },
  1946. {
  1947. fnHandler: 'terminationPlan',
  1948. icoName: 'fa el-icon-error',
  1949. btnName: '终止',
  1950. disabled: this.disableToTermination(row)
  1951. }
  1952. ];
  1953. break;
  1954. case 1:
  1955. this.contextTableMenuData.menulists = [
  1956. {
  1957. fnHandler: 'addTask',
  1958. icoName: 'fa el-icon-plus',
  1959. btnName: '新建任务',
  1960. disabled: this.disableToAddTask(row)
  1961. },
  1962. // {fnHandler: 'editBOM', icoName: 'fa el-icon-edit', btnName: '修改'},
  1963. // {fnHandler: 'removeBom', icoName: 'fa el-icon-delete', btnName: '删除'},
  1964. {
  1965. fnHandler: 'finishPlanStage',
  1966. icoName: 'fa el-icon-success',
  1967. btnName: '完成',
  1968. disabled: this.disableToFinish(row)
  1969. },
  1970. {
  1971. fnHandler: 'pausePlanStage',
  1972. icoName: 'fa el-icon-video-pause',
  1973. btnName: '暂停',
  1974. disabled: this.disableToPause(row)
  1975. },
  1976. {
  1977. fnHandler: 'startupPlanStage',
  1978. icoName: 'fa el-icon-video-play',
  1979. btnName: '启动',
  1980. disabled: this.disableToStartup(row)
  1981. },
  1982. {
  1983. fnHandler: 'terminationPlanStage',
  1984. icoName: 'fa el-icon-error',
  1985. btnName: '终止',
  1986. disabled: this.disableToTermination(row)
  1987. }
  1988. ];
  1989. break;
  1990. case 2:
  1991. this.contextTableMenuData.menulists = [
  1992. {
  1993. fnHandler: 'addTask',
  1994. icoName: 'fa el-icon-plus',
  1995. btnName: '新建任务',
  1996. disabled: [4, 2, 3].includes(row.status)
  1997. },
  1998. {
  1999. fnHandler: 'updateTask',
  2000. icoName: 'fa el-icon-edit',
  2001. btnName: '修改',
  2002. disabled: [4, 2, 3, 1].includes(row.status)
  2003. },
  2004. {
  2005. fnHandler: 'removeTask',
  2006. icoName: 'fa el-icon-delete',
  2007. btnName: '删除',
  2008. disabled: [4, 2, 3, 1].includes(row.status)
  2009. },
  2010. {
  2011. fnHandler: 'startTask',
  2012. icoName: 'fa el-icon-video-play',
  2013. btnName: '执行',
  2014. disabled: [4, 3, 1].includes(row.status)
  2015. },
  2016. {
  2017. fnHandler: 'handleSubmitDeliverables',
  2018. icoName: 'fa el-icon-folder-add',
  2019. btnName: '交付物提交',
  2020. disabled: [4, 3, 0, 2].includes(row.status)
  2021. },
  2022. {
  2023. fnHandler: 'finishTask',
  2024. icoName: 'fa el-icon-success',
  2025. btnName: '报工',
  2026. disabled: !(
  2027. [1].includes(row.status) && row.ifFilesAllFinish == 1
  2028. )
  2029. },
  2030. {
  2031. fnHandler: 'pauseTask',
  2032. icoName: 'fa el-icon-video-pause',
  2033. btnName: '暂停',
  2034. disabled: this.disableToPause(row)
  2035. },
  2036. {
  2037. fnHandler: 'terminationTask',
  2038. icoName: 'fa el-icon-error',
  2039. btnName: '终止',
  2040. disabled: this.disableToTermination(row)
  2041. },
  2042. {
  2043. fnHandler: 'handleTransfer',
  2044. icoName: 'fa el-icon-position',
  2045. btnName: '转派',
  2046. disabled: ![1].includes(row.status)
  2047. }
  2048. ];
  2049. break;
  2050. }
  2051. });
  2052. },
  2053. //转派
  2054. handleTransfer(row) {
  2055. this.transferDialogFlag = true;
  2056. this.$nextTick(() => {
  2057. this.$refs.transferDialogRef.init(row);
  2058. });
  2059. },
  2060. /* 交付物提交 */
  2061. handleSubmitDeliverables(row = {}, type) {
  2062. this.submitDeliverablesDialogFlag = true;
  2063. this.$nextTick(() => {
  2064. this.$refs.submitDeliverablesDialogRef.init(row, type);
  2065. });
  2066. },
  2067. async getProjectTaskInfo(id = '') {
  2068. this.rightForm = await projectsTaskGetByIdAPI(id);
  2069. this.rightForm.type = this.rightForm.type + '';
  2070. this.rightForm.responsibleUserIds =
  2071. this.rightForm.responsibleUserList?.map((i) => i.userName) || [];
  2072. },
  2073. async getProjectPlanInfo(id = '') {
  2074. let res = await projectsPlanGetByIdAPI(id);
  2075. this.rightForm = deepClone(res);
  2076. this.rightForm.responsibleUserIds =
  2077. this.rightForm.responsibleUserList?.map((i) => i.userName) || [];
  2078. this.rightForm.planStageList?.forEach((item, index) => {
  2079. let userNames = item.responsibleUserList.map((i) => i.userName) || [];
  2080. this.$set(item, 'responsibleUserNames', userNames.join(','));
  2081. });
  2082. // await this.changeProject(this.dialogForm.projectId)
  2083. },
  2084. async getTeamInfo(teamId) {
  2085. if (teamId) {
  2086. this.teamForm = await projectsTeamGetByIdAPI(teamId);
  2087. }
  2088. },
  2089. // 每一级字体变小
  2090. fontSize(node, data) {
  2091. if (node.level === 1 || node.level === 2) return 'font-size:14px'; // 一二级字体
  2092. return 'font-size:' + 13 + 'px'; // 三级以下字号减小
  2093. },
  2094. uploadFile() {
  2095. this.$refs.importDialogRef.open();
  2096. },
  2097. handleLeftTreeActiveName(val) {
  2098. console.log(val);
  2099. this.leftTreeActiveName = val;
  2100. this.getTreeData();
  2101. },
  2102. customColorMethod(percentage) {
  2103. if (percentage < 30) {
  2104. return '#b6b6b6';
  2105. } else if (percentage < 70) {
  2106. return '#b3e496';
  2107. } else {
  2108. return '#67c23a';
  2109. }
  2110. }
  2111. }
  2112. };
  2113. </script>
  2114. <style lang="scss" scoped>
  2115. .ele-body {
  2116. display: flex;
  2117. flex-direction: column;
  2118. height: 100%;
  2119. .card_2_box {
  2120. flex: 1;
  2121. ::v-deep .el-card__body {
  2122. height: 100%;
  2123. .card_2_box_content {
  2124. height: 100%;
  2125. .ele-split-panel {
  2126. height: 100%;
  2127. .el_tree_box {
  2128. padding: 0 4px 0 0;
  2129. height: 100%;
  2130. border: none;
  2131. border-right: 1px solid #e8eaec;
  2132. //border-radius: 3px;
  2133. .el-tree-node {
  2134. .el-tree-node__children {
  2135. height: 100%;
  2136. overflow: auto;
  2137. }
  2138. }
  2139. }
  2140. }
  2141. }
  2142. }
  2143. }
  2144. }
  2145. .card_2_layout_content {
  2146. display: flex;
  2147. flex-direction: column;
  2148. height: 100%;
  2149. ::v-deep .card_2_1_box {
  2150. height: 50px;
  2151. width: 100%;
  2152. margin-bottom: 10px;
  2153. .border-box-content {
  2154. height: 100%;
  2155. width: 100%;
  2156. background: rgba(203, 203, 203, 0.12);
  2157. border-radius: 3px;
  2158. display: flex;
  2159. flex-direction: row;
  2160. justify-content: space-between;
  2161. align-items: center;
  2162. .card_2_1_box_div_1 {
  2163. flex: 1;
  2164. height: 50px;
  2165. display: flex;
  2166. align-items: center;
  2167. .el-steps--simple {
  2168. border-radius: 0 !important;
  2169. background: none;
  2170. width: 100%;
  2171. padding: 10px 8%;
  2172. }
  2173. .is-success {
  2174. color: rgb(103, 103, 103) !important;
  2175. .el-step__icon {
  2176. border-color: rgb(103, 103, 103) !important;
  2177. }
  2178. .el-icon-check:before {
  2179. font-size: 14px;
  2180. line-height: 14px;
  2181. font-weight: bold;
  2182. color: rgb(103, 103, 103) !important;
  2183. }
  2184. }
  2185. .el-step__main {
  2186. .is-process:before {
  2187. content: '';
  2188. background: rgba(182, 182, 182, 0.26);
  2189. height: 30px;
  2190. width: 160px;
  2191. display: block;
  2192. position: absolute;
  2193. border-radius: 15px;
  2194. transform: translate(-40%, -18%);
  2195. }
  2196. }
  2197. .is-process {
  2198. border-color: #f8f8f8 !important;
  2199. font-weight: bold;
  2200. }
  2201. .is-success + .el-step__arrow:before {
  2202. background: rgb(202, 205, 212) !important;
  2203. }
  2204. .is-success + .el-step__arrow:after {
  2205. background: rgb(202, 205, 212) !important;
  2206. }
  2207. }
  2208. .card_2_1_box_div_2 {
  2209. width: 150px;
  2210. margin-right: 10px;
  2211. height: 100%;
  2212. display: flex;
  2213. align-items: center;
  2214. .dv-percent-pond text {
  2215. font-size: 20px !important;
  2216. transform: translate(0%, 10%);
  2217. }
  2218. }
  2219. }
  2220. }
  2221. ::v-deep .tab-box_1 {
  2222. flex: 1;
  2223. .el-tabs__content {
  2224. //padding: 10px;
  2225. height: calc(100% - 45px);
  2226. //overflow: auto;
  2227. padding: 0;
  2228. padding-top: 10px;
  2229. .el-tab-pane {
  2230. height: 100%;
  2231. }
  2232. }
  2233. }
  2234. }
  2235. ::v-deep .project_tree {
  2236. .custom-tree-node {
  2237. display: flex;
  2238. align-items: center;
  2239. .label_img {
  2240. width: 20px;
  2241. height: 20px;
  2242. margin-left: 5px;
  2243. }
  2244. }
  2245. .el-tree-node {
  2246. position: relative;
  2247. padding-left: 0px;
  2248. }
  2249. .el-tree-node__children {
  2250. padding-left: 22px;
  2251. }
  2252. // 自定义图标中隐藏自带箭头
  2253. //.el-tree-node__content > .el-tree-node__expand-icon {
  2254. // position: absolute;
  2255. // opacity: 0;
  2256. //}
  2257. .el-tree-node__content > .el-tree-node__expand-icon {
  2258. padding: 0;
  2259. }
  2260. // 禁止旋转
  2261. .el-tree .el-tree-node__expand-icon.expanded {
  2262. -webkit-transform: rotate(0deg);
  2263. transform: rotate(0deg);
  2264. }
  2265. // 节点高度与边距
  2266. .el-tree-node__content {
  2267. height: 30px;
  2268. }
  2269. .el-tree-node {
  2270. margin: 1px 0;
  2271. overflow: hidden;
  2272. text-overflow: ellipsis;
  2273. white-space: nowrap;
  2274. }
  2275. //高亮字体颜色
  2276. .el-tree--highlight-current
  2277. .el-tree-node.is-current
  2278. > .el-tree-node__content {
  2279. color: #ee7355 !important;
  2280. background-color: red !important; // 设置选中背景颜色
  2281. }
  2282. // 设置竖线
  2283. .el-tree-node .is-focusable:before {
  2284. content: '';
  2285. display: inline-block;
  2286. position: absolute;
  2287. left: -15px;
  2288. border-left: 1px solid #f8f8f8;
  2289. height: calc(100%);
  2290. }
  2291. .list-left {
  2292. width: 214px;
  2293. height: auto;
  2294. margin: 10px 0 20px 20px;
  2295. background-color: #fff;
  2296. border-radius: 10px;
  2297. padding: 20px;
  2298. }
  2299. // 鼠标移入高亮
  2300. .custom-tree-node:hover {
  2301. //color: #070a0c !important;
  2302. }
  2303. .el-icon-folder-opened,
  2304. .el-icon-folder,
  2305. .el-icon-document,
  2306. .el-icon-tickets {
  2307. display: flex;
  2308. align-items: center;
  2309. }
  2310. .el-icon-document,
  2311. .el-icon-folder-opened {
  2312. //color: #0e85fa;
  2313. }
  2314. //高亮字体颜色
  2315. .el-tree--highlight-current,
  2316. .el-tree-node.is-current > .el-tree-node__content {
  2317. color: #f8f8f8 !important;
  2318. background-color: #72b9ff !important; // 设置选中背景颜色
  2319. border-radius: 3px;
  2320. }
  2321. .el-tree-node__content:hover {
  2322. color: #f8f8f8 !important;
  2323. background-color: #b7d6f8 !important; // 设置选中背景颜色
  2324. border-radius: 3px;
  2325. }
  2326. }
  2327. ::v-deep .ele-table-tool-default {
  2328. display: none;
  2329. }
  2330. ::v-deep .ele-split-panel-body {
  2331. .ele-split-panel-side {
  2332. border-bottom: 1px solid #e8e8e8;
  2333. }
  2334. }
  2335. ::v-deep .ele-split-panel-side {
  2336. // border-bottom: 2px solid #e6e8ea;
  2337. height: 100%;
  2338. .tab-box_1 {
  2339. height: 100%;
  2340. .el-tabs__item {
  2341. background: rgba(246, 246, 247, 0.8);
  2342. border-bottom: 1px solid #e6e8ea;
  2343. }
  2344. .is-active.el-tabs__item {
  2345. background: #ffffff;
  2346. border-bottom: none;
  2347. }
  2348. .el-table {
  2349. height: calc(100% - 1px);
  2350. }
  2351. }
  2352. }
  2353. ::v-deep .tab-box_2 {
  2354. height: 100%;
  2355. overflow: auto;
  2356. display: flex;
  2357. flex-direction: column;
  2358. .el-tabs__content {
  2359. flex: 1;
  2360. .el-tab-pane {
  2361. height: 100%;
  2362. }
  2363. }
  2364. }
  2365. .current_button {
  2366. background: #096cd7;
  2367. border-color: #096cd7;
  2368. color: #ffffff;
  2369. }
  2370. ::v-deep .vue-contextmenu-listWrapper {
  2371. display: block;
  2372. background: #fff !important;
  2373. padding: 4px 0 !important;
  2374. border: 1px solid #dadada;
  2375. border-radius: 7px !important;
  2376. color: #606266;
  2377. .context-menu-list:hover {
  2378. background: rgba(156, 156, 156, 0.2) !important;
  2379. //color: #FFFFFF !important;
  2380. }
  2381. .context-menu-list {
  2382. background: #fff !important;
  2383. width: 100%;
  2384. height: 25px;
  2385. div {
  2386. display: flex;
  2387. flex-direction: row;
  2388. align-items: center;
  2389. justify-content: flex-start;
  2390. min-width: 120px;
  2391. width: 100%;
  2392. height: 100%;
  2393. i {
  2394. margin-left: 15px;
  2395. }
  2396. span {
  2397. margin: 0 !important;
  2398. margin-left: 25px !important;
  2399. }
  2400. }
  2401. }
  2402. }
  2403. ::v-deep tr[class^='el-table__row--level'] > td:nth-child(2) > .cell {
  2404. margin-left: 24px;
  2405. }
  2406. ::v-deep .el-table__header-wrapper .el-table__cell {
  2407. .cell {
  2408. text-align: center;
  2409. }
  2410. }
  2411. @for $i from 1 to 10 {
  2412. ::v-deep .el-table__row--level-#{$i} > td:nth-child(2) > .cell {
  2413. margin-left: #{$i * 4 +10}px;
  2414. display: flex;
  2415. flex-direction: row;
  2416. align-items: center;
  2417. }
  2418. }
  2419. .dot {
  2420. border-radius: 50%;
  2421. -webkit-background-clip: text;
  2422. color: #0e85fa;
  2423. display: inline-block;
  2424. width: 5px;
  2425. height: 5px;
  2426. margin-right: 2px;
  2427. text-align: center;
  2428. background: #0e85fa;
  2429. }
  2430. </style>