wbs-tree.vue 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341
  1. <template>
  2. <hc-drawer v-model="isShow" is-close to-id="hc-project-list">
  3. <div class="hc-project-wbs-tree flex">
  4. <div class="header hc-flex">
  5. <div class="name flex-1">
  6. {{ typeLable }} - {{ projectInfo.projectName }}
  7. </div>
  8. <div class="hc-flex">
  9. <el-dropdown trigger="click">
  10. <el-button hc-btn type="success">
  11. <span>数据同步</span>
  12. <hc-icon name="arrow-down-s" />
  13. </el-button>
  14. <template #dropdown>
  15. <el-dropdown-menu>
  16. <template
  17. v-for="item in dataSyncMenu"
  18. :key="item.key"
  19. >
  20. <el-dropdown-item
  21. @click="dataSyncMenuClick(item)"
  22. >{{ item.name }}</el-dropdown-item
  23. >
  24. </template>
  25. </el-dropdown-menu>
  26. </template>
  27. </el-dropdown>
  28. <el-button
  29. v-if="isFormSet"
  30. class="ml-3"
  31. hc-btn
  32. type="primary"
  33. @click="setIsFormSetValue"
  34. >表单设置</el-button
  35. >
  36. <el-button
  37. v-else
  38. class="ml-3"
  39. hc-btn
  40. type="primary"
  41. @click="setIsFormSetValue"
  42. >元素设置</el-button
  43. >
  44. <el-button hc-btn type="danger" @click="nodeParamClick"
  45. >节点参数</el-button
  46. >
  47. <el-button hc-btn color="#626aef" @click="toIndependent"
  48. >独立表单库</el-button
  49. >
  50. <el-button hc-btn type="warning" @click="archiveClick"
  51. >归档文件时间</el-button
  52. >
  53. </div>
  54. </div>
  55. <div class="body">
  56. <hc-body split padding="8px">
  57. <template #left>
  58. <hc-card
  59. v-loading="isTreeLoading"
  60. title="工程节点信息"
  61. scrollbar
  62. class="is-tree"
  63. >
  64. <template #search>
  65. <hc-search-input
  66. v-model="searchTree.queryValue"
  67. @search="searchTreeClick"
  68. >
  69. <template #prepend>
  70. <el-select
  71. v-model="searchTree.type"
  72. placeholder="类型"
  73. style="width: 75px"
  74. >
  75. <el-option label="节点" value="1" />
  76. <el-option label="表名" value="2" />
  77. </el-select>
  78. </template>
  79. </hc-search-input>
  80. </template>
  81. <hc-data-tree
  82. v-if="isSearchTree"
  83. :h-props="treeProps"
  84. :datas="treeLoadData"
  85. tree-key="id"
  86. :auto-expand-keys="treeExpandKeys"
  87. :menus="treeMenus"
  88. @menu-tap="treeMenuClick"
  89. @node-tap="treeNodeClick"
  90. />
  91. <hc-lazy-tree
  92. v-else
  93. :h-props="treeProps"
  94. tree-key="id"
  95. :auto-expand-keys="treeExpandKeys"
  96. :menus="treeMenus"
  97. @load="treeLoadNode"
  98. @menu-tap="treeMenuClick"
  99. @node-tap="treeNodeClick"
  100. />
  101. </hc-card>
  102. </template>
  103. <template v-if="isFormSet">
  104. <div class="body-top">
  105. <hc-card title="节点信息">
  106. <hc-table
  107. :is-index="false"
  108. :column="nodeTableColumn"
  109. :datas="nodeTableData"
  110. >
  111. <template #nodeType="{ row }">{{
  112. getDictionaryName(
  113. nodeTypelist,
  114. row.nodeType,
  115. true
  116. )
  117. }}</template>
  118. </hc-table>
  119. </hc-card>
  120. </div>
  121. <div class="body-content">
  122. <hc-card title="当前项目信息表">
  123. <template #extra>
  124. <el-button
  125. hc-btn
  126. type="primary"
  127. :disabled="infoTableData.length <= 0"
  128. @click="editRowClick(row)"
  129. >编辑</el-button
  130. >
  131. <el-button
  132. @click="sortClick"
  133. hc-btn
  134. type="success"
  135. :disabled="infoTableData.length <= 0"
  136. >排序</el-button
  137. >
  138. </template>
  139. <hc-table
  140. v-loading="infoTableLoading"
  141. :is-index="false"
  142. :column="infoTableColumn"
  143. :datas="infoTableData"
  144. >
  145. <template #tableType="{ row }">{{
  146. getDictionaryName(
  147. tableTypelist,
  148. row.tableType,
  149. true
  150. )
  151. }}</template>
  152. <template #tableOwner="{ row }">{{
  153. getDictionaryName(
  154. ownerTypeList,
  155. row.tableOwner,
  156. true
  157. )
  158. }}</template>
  159. <template #action="{ row }">
  160. <el-link
  161. type="primary"
  162. @click="previewClick(row)"
  163. >预览</el-link
  164. >
  165. <el-link
  166. @click="hideClick(row)"
  167. v-if="row.status === 1"
  168. type="warning"
  169. >隐藏表单</el-link
  170. >
  171. <el-link
  172. @click="hideClick(row)"
  173. v-if="row.status === 0"
  174. type="success"
  175. >取消隐藏</el-link
  176. >
  177. <el-link
  178. type="primary"
  179. @click="handleEdit(row)"
  180. >编辑</el-link
  181. >
  182. <el-link
  183. v-del-com:[delInfoTableRow]="row"
  184. type="danger"
  185. >删除</el-link
  186. >
  187. </template>
  188. </hc-table>
  189. </hc-card>
  190. </div>
  191. </template>
  192. <template v-else>
  193. <hc-card>
  194. <hc-table
  195. v-loading="infoTableLoading"
  196. :is-index="false"
  197. :column="infoTableColumn1"
  198. :datas="infoTableData"
  199. >
  200. <template #tableType="{ row }">{{
  201. getDictionaryName(
  202. tableTypelist,
  203. row.tableType,
  204. true
  205. )
  206. }}</template>
  207. <template #isLinkTable="{ row }">{{
  208. row.isLinkTable === 2 ? "是" : "否"
  209. }}</template>
  210. <template #tableOwner="{ row }">{{
  211. getDictionaryName(
  212. ownerTypeList,
  213. row.tableOwner,
  214. true
  215. )
  216. }}</template>
  217. <template #action="{ row }">
  218. <el-link
  219. type="success"
  220. @click="associationList(row)"
  221. >关联清表</el-link
  222. >
  223. <el-link
  224. v-loading="editElementLoading"
  225. type="primary"
  226. :disabled="
  227. row.excelId === -1 ||
  228. isNullES(row.excelId)
  229. "
  230. @click="editElement(row)"
  231. >编辑元素</el-link
  232. >
  233. <el-link
  234. v-loading="adjustExcelLoading"
  235. type="warning"
  236. :disabled="
  237. row.excelId === -1 ||
  238. isNullES(row.excelId)
  239. "
  240. @click="adjustExcelClick(row)"
  241. >调整表单</el-link
  242. >
  243. <el-link
  244. type="primary"
  245. @click="elementFormulasClick(row)"
  246. >编辑元素公式</el-link
  247. >
  248. <el-link
  249. type="warning"
  250. @click="syncTable(row)"
  251. v-loading="syncTableLoading"
  252. >表单同步</el-link
  253. >
  254. <el-link
  255. v-if="
  256. treeItem.nodeType === 1000 ||
  257. treeItem.nodeType === 1001
  258. "
  259. type="primary"
  260. @click="linkNodeClick(row)"
  261. >关联节点</el-link
  262. >
  263. <el-link
  264. v-del-com:[delInfoTableRow]="row"
  265. type="danger"
  266. >删除表单</el-link
  267. >
  268. </template>
  269. </hc-table>
  270. </hc-card>
  271. </template>
  272. </hc-body>
  273. </div>
  274. </div>
  275. <!-- 编辑节点 -->
  276. <TreeNodeEditDialog
  277. v-model="isTreeNodeEditShow"
  278. :node="treeInfo"
  279. :type="Number(isType)"
  280. :wid="wbsId"
  281. :pid="projectInfo.id"
  282. :tree-props="treeProps"
  283. :node-type="nodeTypelist"
  284. :major-type="majorDataTypeList"
  285. @close="treeNodeEditClose"
  286. @change="treeNodeEditChange"
  287. />
  288. <!-- 节点排序 -->
  289. <hc-new-dialog
  290. v-model="nodeSortModalShow"
  291. is-table
  292. widths="1100px"
  293. title="调整排序"
  294. @save="nodeSortModalSave"
  295. >
  296. <hc-table
  297. ui="hc-table-row-drop"
  298. :column="nodeSortTableColumn"
  299. :datas="nodeSortTableData"
  300. :loading="nodeSortNodeLoading"
  301. is-row-drop
  302. quick-sort
  303. :index-style="{ width: 80 }"
  304. @row-drop="nodeSortTableRowDrop"
  305. @row-sort="nodeSortTableRowDrop"
  306. >
  307. <template #action="{ row, index }">
  308. <span
  309. class="text-xl"
  310. :class="index === 0 ? 'text-gray' : 'text-link'"
  311. @click="upNodeSortClick(row, index)"
  312. >
  313. <hc-icon name="arrow-up" fill />
  314. </span>
  315. <span
  316. class="ml-2 text-xl"
  317. :class="
  318. index === nodeSortTableData.length - 1
  319. ? 'text-gray'
  320. : 'text-link'
  321. "
  322. @click="downNodeSortClick(row, index)"
  323. >
  324. <hc-icon name="arrow-down" fill />
  325. </span>
  326. </template>
  327. </hc-table>
  328. </hc-new-dialog>
  329. <!-- 关联清表 -->
  330. <HcAssociationList
  331. v-model="isAssociationShow"
  332. :info="associationInfo"
  333. @change="getInfoTableData"
  334. />
  335. <!-- 编辑元素 -->
  336. <HcEditElement
  337. v-model="isEditElementShow"
  338. :info="editElementInfo"
  339. :data="editElementData"
  340. @to-page="editElementToPage"
  341. />
  342. <!-- 调整表单 -->
  343. <HcAdjustExcel v-model="isAdjustExcelShow" :info="adjustExcelInfo" />
  344. <!-- 编辑元素公式 -->
  345. <hc-dialog
  346. v-model="elementFormulasShow"
  347. is-table
  348. widths="600px"
  349. :title="elementFormulasName"
  350. :footer="false"
  351. @close="elementFormulasClose"
  352. >
  353. <template #search>
  354. <hc-search-input
  355. v-model="formulaInput"
  356. @search="searchFormulaClick"
  357. />
  358. </template>
  359. <hc-table
  360. v-loading="formulaTableLoading"
  361. :is-index="false"
  362. :is-current-row="false"
  363. :column="formulaTableColumn"
  364. :datas="formulaTableData"
  365. >
  366. <template #action="{ row }">
  367. <el-link
  368. :type="row.globalFormula === 1 ? 'warning' : 'primary'"
  369. @click="toFormulaGlobal(row)"
  370. >全局公式</el-link
  371. >
  372. <el-link
  373. v-show="row.hasPartFormula"
  374. :type="row.isSaveFormula === 1 ? 'warning' : 'primary'"
  375. @click="toFormulaNodes(row)"
  376. >节点公式</el-link
  377. >
  378. </template>
  379. </hc-table>
  380. </hc-dialog>
  381. <!-- 编辑公式 -->
  382. <HcEditFormula
  383. v-model="isEditFormulaShow"
  384. :data="editFormulaData"
  385. @finish="editFormulaFinish"
  386. />
  387. <!-- 节点参数设置 -->
  388. <nodeParamDialog
  389. v-model="nodeParamShow"
  390. @close="nodeParamClose"
  391. :nodeId="treeItem.id"
  392. :nodeInfo="treeItem"
  393. :porjectId="projectInfo.id"
  394. :scopeType="10"
  395. >
  396. </nodeParamDialog>
  397. <!-- 独立表单库 -->
  398. <independentPage
  399. @close="independentClose"
  400. v-model="independentShow"
  401. :wbsType="isType"
  402. :projectId="projectInfo.id"
  403. :wbsId="wbsId"
  404. ></independentPage>
  405. <!-- 归档文件时间 -->
  406. <archiveTime v-model="isArchiveShow"></archiveTime>
  407. <!-- 编辑元素表信息 -->
  408. <editElePage
  409. v-model="editEleShow"
  410. @close="editClose"
  411. :tableTypelist="tableTypelist"
  412. :ownerTypeList="ownerTypeList"
  413. :tab="infoTableData"
  414. ></editElePage>
  415. <!-- 表单调整排序 -->
  416. <tableSort
  417. v-model="tableSortShow"
  418. @close="tableSortShowClose"
  419. :tab="infoTableData"
  420. >
  421. </tableSort>
  422. <!-- 预览 -->
  423. <previewPage v-model="previewShow" :info="previewInfo"></previewPage>
  424. <!-- 创建新的元素表 -->
  425. <createNewExcel
  426. v-model="isCreateShow"
  427. @close="createClose"
  428. :node="treeItem"
  429. :wid="wbsId"
  430. :tableTypelist="tableTypelist"
  431. :ownerTypeList="ownerTypeList"
  432. :title="modalTitle"
  433. :initTableName="initTableName"
  434. :initTableId="initTableId"
  435. :tableId="tableId"
  436. :eKey="eKey"
  437. :type="0"
  438. ></createNewExcel>
  439. <!-- 分配WBS -->
  440. <allocateWbs
  441. v-model="isAllocateShow"
  442. :wbsType="isType"
  443. :projectId="projectInfo.id"
  444. :data="allocateWbsInfo"
  445. :type="1"
  446. ></allocateWbs>
  447. </hc-drawer>
  448. </template>
  449. <script setup>
  450. import { nextTick, onDeactivated, ref, watch } from "vue";
  451. import { useAppStore } from "~src/store";
  452. import { HcFirmMsg, getStore, setStore } from "hc-vue3-ui";
  453. import { deepClone, getArrValue, getObjValue, isNullES } from "js-fast-way";
  454. import { getDictionaryData, reloadPage } from "~uti/tools";
  455. import TreeNodeEditDialog from "./tree-node-edit.vue";
  456. import HcAdjustExcel from "./adjust-excel.vue";
  457. import HcAssociationList from "./association-list.vue";
  458. import HcEditElement from "./edit-element.vue";
  459. import HcEditFormula from "./edit-formula.vue";
  460. import excelApi from "~api/exctab/exceltab";
  461. import wbsTreeApi from "~api/wbs/tree";
  462. import mainApi from "~api/wbs/private";
  463. import nodeParamDialog from "../../desk/wbs/node-param-dialog.vue";
  464. import independentPage from "./independent/index.vue";
  465. import archiveTime from "./archiveTime.vue";
  466. import editElePage from "../../desk/wbs/edit-ele.vue";
  467. import tableSort from "../../desk/wbs/table-sort.vue";
  468. import previewPage from "./previewPage.vue";
  469. import createNewExcel from "../../desk/wbs/create-new-excel.vue";
  470. import allocateWbs from "../list/independent/allocateWbs.vue";
  471. const props = defineProps({
  472. type: {
  473. type: [String, Number],
  474. default: "1",
  475. },
  476. info: {
  477. type: Object,
  478. default: () => ({}),
  479. },
  480. });
  481. //事件
  482. const emit = defineEmits(["change", "close"]);
  483. //双向绑定
  484. // eslint-disable-next-line no-undef
  485. const isShow = defineModel("modelValue", {
  486. default: false,
  487. });
  488. const store = useAppStore();
  489. //监听数据
  490. const isType = ref(props.type);
  491. const projectInfo = ref(props.info);
  492. watch(
  493. () => [props.type, props.info],
  494. ([type, info]) => {
  495. isType.value = type;
  496. projectInfo.value = info;
  497. },
  498. { deep: true }
  499. );
  500. //监听显示
  501. watch(isShow, (val) => {
  502. if (val) {
  503. getProjectData();
  504. } else {
  505. //projectInfo.value = {}
  506. //isType.value = ''
  507. emit("close");
  508. }
  509. });
  510. //获取项目信息
  511. const typeLable = ref("");
  512. const wbsId = ref("");
  513. const getProjectData = () => {
  514. const type = isType.value ?? 1;
  515. const wbsArr = [
  516. "WBS树管理",
  517. "实验划分",
  518. "计量管理",
  519. "日志树管理",
  520. "征拆划分",
  521. ];
  522. typeLable.value = wbsArr[Number(type) - 1];
  523. const wbsIds = [
  524. "referenceWbsTemplateId",
  525. "referenceWbsTemplateIdTrial",
  526. "referenceWbsTemplateIdMeter",
  527. "referenceLogWbsTemplateId",
  528. "referenceWbsTemplateIdLar",
  529. ];
  530. wbsId.value = projectInfo.value[wbsIds[Number(type) - 1]];
  531. console.log("info: ", projectInfo.value);
  532. getNodeTypelist(Number(type) - 1);
  533. getTableTypelist(Number(type) - 1);
  534. getDataTypelist();
  535. getOwnerTypelist();
  536. getMajorDataTypeList();
  537. };
  538. //获取节点类型
  539. const nodeTypelist = ref([]);
  540. const getNodeTypelist = async (type) => {
  541. //计量管理,征拆划分,实验划分,WBS树管理,日志树管理
  542. const types = [
  543. "wbs_node_type",
  544. "trial_node_type",
  545. "meter_node_type",
  546. "wbs_node_type",
  547. "lar_node_type",
  548. ];
  549. const data = await getDictionaryData(types[type]);
  550. nodeTypelist.value = getArrValue(data);
  551. };
  552. //获取表单类型
  553. const tableTypelist = ref([]);
  554. const getTableTypelist = async (type) => {
  555. //计量管理,征拆划分,实验划分,WBS树管理,日志树管理
  556. const types = [
  557. "table_type",
  558. "trial_table_type",
  559. "table_type",
  560. "table_type",
  561. "table_type",
  562. ];
  563. const data = await getDictionaryData(types[type]);
  564. tableTypelist.value = getArrValue(data);
  565. };
  566. //获取数据类型
  567. const dataTypeList = ref([]);
  568. const getDataTypelist = async () => {
  569. const data = await getDictionaryData("data_type");
  570. dataTypeList.value = getArrValue(data);
  571. };
  572. //获取业主类型
  573. const ownerTypeList = ref([]);
  574. const getOwnerTypelist = async () => {
  575. const data = await getDictionaryData("owner_type");
  576. ownerTypeList.value = getArrValue(data);
  577. };
  578. //获取类型字典
  579. const majorDataTypeList = ref([]);
  580. const getMajorDataTypeList = async () => {
  581. const data = await getDictionaryData("major_data_type");
  582. majorDataTypeList.value = getArrValue(data);
  583. };
  584. //获取字典里的数据
  585. const getDictionaryName = (arr, id, name) => {
  586. if (isNullES(id)) return name ? "" : {};
  587. const item = arr.find((item) => item.value === Number(id));
  588. return name ? item?.label : getObjValue(item);
  589. };
  590. //树节点搜索
  591. const isSearchTree = ref(false);
  592. const isTreeLoading = ref(false);
  593. const searchTree = ref({ queryValue: "", type: "1" });
  594. const searchTreeClick = () => {
  595. const { queryValue } = searchTree.value;
  596. isSearchTree.value = !isNullES(queryValue);
  597. getTreeLoadData();
  598. };
  599. //获取搜索树的数据
  600. const treeLoadData = ref([]);
  601. const getTreeLoadData = async () => {
  602. isTreeLoading.value = true;
  603. const { data } = await wbsTreeApi.getQueryValueByType({
  604. ...searchTree.value,
  605. wbsId: wbsId.value,
  606. projectId: projectInfo.value.id,
  607. });
  608. treeLoadData.value = getArrValue(data);
  609. isTreeLoading.value = false;
  610. };
  611. //树属性
  612. const treeExpandKeys = ref(getStore("project-wbs-tree-expand-keys") || []);
  613. const treeProps = {
  614. children: "children",
  615. label: "title",
  616. isLeaf: ({ hasChildren, isExistForm, majorDataType, nodeType }) => {
  617. let tag = false;
  618. if (!hasChildren) {
  619. tag = true;
  620. }
  621. if (isExistForm === 1) {
  622. tag = true;
  623. }
  624. if (nodeType >= 6 && nodeType <= 13) {
  625. tag = true;
  626. }
  627. //中间交工。开工报告、质量评定)
  628. if (majorDataType >= 1 && majorDataType <= 3) {
  629. tag = true;
  630. }
  631. return tag;
  632. },
  633. };
  634. //树的右键菜单
  635. const treeMenus = [
  636. { icon: "draft", label: "编辑节点", key: "edit" },
  637. { icon: "refresh", label: "同步新增元素表单", key: "sync1" },
  638. { icon: "loop-left", label: "同步元素表单排序到合同段", key: "sync3" },
  639. { icon: "loop-right", label: "同步节点基础信息及表单URL", key: "sync2" },
  640. { icon: "arrow-up-down", label: "调整排序", key: "rank" },
  641. { icon: "delete-bin", label: "删除节点", key: "del" },
  642. ];
  643. //菜单被点击
  644. const treeMenuItem = ref({});
  645. const treeMenuClick = async ({ key, node, data }) => {
  646. if (key === "edit") {
  647. //编辑节点
  648. data.parentName = node?.parent?.data?.title ?? ""; //获取父节点名称
  649. treeItem.value = data;
  650. await getTreeDetail();
  651. await nextTick();
  652. isTreeNodeEditShow.value = true;
  653. } else if (key === "sync1") {
  654. const { primaryKeyId, pKeyId } = data;
  655. const pid = primaryKeyId ? primaryKeyId : pKeyId;
  656. if (isNullES(pid)) {
  657. window.$message.warning("参数异常,请稍后重试");
  658. return;
  659. }
  660. //同步新增元素表单
  661. HcFirmMsg(
  662. {
  663. text: `是否同步节点【${data.title}】?`,
  664. loadingText: "数据同步中...",
  665. },
  666. async (resolve) => {
  667. const { isRes } = await mainApi.syncNodeTable(pid);
  668. resolve(); //关闭弹窗
  669. if (!isRes) return;
  670. window.$message.success("同步成功");
  671. getInfoTableData();
  672. }
  673. );
  674. } else if (key === "sync3") {
  675. const { id } = projectInfo.value;
  676. if (isNullES(id)) {
  677. window.$message.warning("参数异常,请稍后重试");
  678. return;
  679. }
  680. //同步元素表单排序到合同段
  681. HcFirmMsg(
  682. {
  683. text: "同步元素表单排序到合同段?",
  684. loadingText: "数据同步中...",
  685. },
  686. async (resolve) => {
  687. const { isRes } = await mainApi.syncContractTabSort(id);
  688. resolve(); //关闭弹窗
  689. if (!isRes) return;
  690. window.$message.success("同步成功");
  691. getInfoTableData();
  692. }
  693. );
  694. } else if (key === "sync2") {
  695. const { primaryKeyId, pKeyId } = data;
  696. const pid = primaryKeyId ? primaryKeyId : pKeyId;
  697. if (isNullES(pid)) {
  698. window.$message.warning("参数异常,请稍后重试");
  699. return;
  700. }
  701. //同步节点基础信息及表单URL
  702. HcFirmMsg(
  703. {
  704. text: `是否同步节点【${data.title}】到合同段?`,
  705. loadingText: "数据同步中...",
  706. },
  707. async (resolve) => {
  708. const { isRes } = await mainApi.syncNodeinfo(pid);
  709. resolve(); //关闭弹窗
  710. if (!isRes) return;
  711. window.$message.success("同步成功");
  712. getInfoTableData();
  713. }
  714. );
  715. } else if (key === "rank") {
  716. const { parentId } = data;
  717. const { id } = projectInfo.value;
  718. if (isNullES(id) || isNullES(wbsId.value)) {
  719. window.$message.warning("参数异常,请稍后重试");
  720. return;
  721. }
  722. //调整排序
  723. nodeSortModalShow.value = true;
  724. nodeSortNodeLoading.value = true;
  725. const { data: apiData } = await wbsTreeApi.findWbsTreePrivateSameLevel({
  726. parentId: parentId,
  727. projectId: id,
  728. wbsId: wbsId.value,
  729. });
  730. nodeSortNodeLoading.value = false;
  731. nodeSortTableData.value = getArrValue(apiData);
  732. } else if (key === "del") {
  733. if (node.level <= 1) {
  734. window.$message.warning("当前节点无法删除");
  735. return;
  736. }
  737. const { primaryKeyId, pKeyId } = data;
  738. const pid = primaryKeyId ? primaryKeyId : pKeyId;
  739. if (isNullES(pid)) {
  740. window.$message.warning("参数异常,请稍后重试");
  741. return;
  742. }
  743. //删除节点
  744. HcFirmMsg(
  745. {
  746. text: `此操作将删除节点【${data.title}】,是否继续?`,
  747. loadingText: "删除节点中...",
  748. },
  749. async (resolve) => {
  750. const { isRes } = await mainApi.del(pid);
  751. resolve(); //关闭弹窗
  752. if (!isRes) return;
  753. window.$message.success("删除成功");
  754. reloadPage();
  755. }
  756. );
  757. }
  758. };
  759. //节点排序
  760. const nodeSortModalShow = ref(false);
  761. const nodeSortTableColumn = ref([
  762. { key: "tableName", name: "节点名称" },
  763. { key: "action", name: "排序", width: 90 },
  764. ]);
  765. const nodeSortTableData = ref([]);
  766. const nodeSortNodeLoading = ref(false);
  767. //拖动完成
  768. const nodeSortTableRowDrop = (rows) => {
  769. nodeSortTableData.value = []; // 先清空,否则排序会异常
  770. nextTick(() => {
  771. nodeSortTableData.value = rows;
  772. });
  773. };
  774. //向上
  775. const upNodeSortClick = (row, index) => {
  776. const data = nodeSortTableData.value || [];
  777. if (index !== 0) {
  778. const tmp = data.splice(index - 1, 1);
  779. nodeSortTableData.value.splice(index, 0, tmp[0]);
  780. } else {
  781. window?.$message?.warning("已经处于置顶,无法上移");
  782. }
  783. };
  784. //向下
  785. const downNodeSortClick = (row, index) => {
  786. const indexs = index + 1;
  787. const data = nodeSortTableData.value;
  788. if (indexs !== data.length) {
  789. const tmp = data.splice(indexs, 1);
  790. nodeSortTableData.value.splice(index, 0, tmp[0]);
  791. } else {
  792. window?.$message?.warning("已经处于置底,无法下移");
  793. }
  794. };
  795. //节点排序完成
  796. const nodeSortModalSave = async () => {
  797. const arr = deepClone(nodeSortTableData.value);
  798. if (arr.length <= 0) {
  799. window.$message.warning("数据异常,请稍后重试");
  800. nodeSortModalShow.value = false;
  801. return;
  802. }
  803. //处理顺序
  804. for (let i = 0; i < arr.length; i++) {
  805. arr[i].sort = i + 1;
  806. }
  807. //发起请求
  808. const { isRes } = await wbsTreeApi.wbsTreePrivateSort(arr);
  809. if (!isRes) return;
  810. window.$message.success("排序完成");
  811. nodeSortModalShow.value = false;
  812. reloadPage();
  813. };
  814. //编辑节点
  815. const isTreeNodeEditShow = ref(false);
  816. //编辑节点被关闭
  817. const treeNodeEditClose = () => {
  818. isTreeNodeEditShow.value = false;
  819. treeMenuItem.value = {};
  820. };
  821. //编辑节点被修改
  822. const treeNodeEditChange = () => {
  823. isTreeNodeEditShow.value = false;
  824. treeMenuItem.value = {};
  825. console.log("编辑节点被修改");
  826. };
  827. //懒加载树
  828. const treeLoadNode = async ({ item, level }, resolve) => {
  829. let pid = level !== 0 ? item.id : 0;
  830. const { data } = await mainApi.getLazytree({
  831. wbsId: wbsId.value,
  832. parentId: pid,
  833. tenantId: store.tenantId,
  834. projectId: projectInfo.value.id,
  835. wbsType: isType.value,
  836. });
  837. resolve(getArrValue(data));
  838. };
  839. //节点信息
  840. const nodeTableColumn = ref([
  841. { key: "nodeName", name: "当前节点", align: "center" },
  842. { key: "nodeType", name: "节点类型", align: "center" },
  843. { key: "parentName", name: "上级节点", align: "center" },
  844. ]);
  845. const nodeTableData = ref([]);
  846. //节点被点击
  847. const treeItem = ref({});
  848. const nodePid = ref("");
  849. const treeNodeClick = ({ node, data, keys }) => {
  850. nodePid.value = data.primaryKeyId ? data.primaryKeyId : data.pKeyId;
  851. //获取父节点名称
  852. let parentName = "";
  853. if (node?.parent?.data) {
  854. parentName = node.parent.data.title ?? "";
  855. }
  856. data.parentName = parentName;
  857. //设置相关数据
  858. treeItem.value = getObjValue(data);
  859. setStore("project-wbs-tree-expand-keys", keys);
  860. treeExpandKeys.value = getArrValue(keys);
  861. //获取节点详情
  862. getTreeDetail();
  863. getInfoTableData();
  864. };
  865. //获取节点详情
  866. const treeInfo = ref({});
  867. const getTreeDetail = async () => {
  868. const { id, parentName } = treeItem.value;
  869. const { data } = await mainApi.detail({
  870. id,
  871. wbsId: wbsId.value,
  872. projectId: projectInfo.value.id,
  873. });
  874. const res = getObjValue(data);
  875. res.parentName = parentName;
  876. treeInfo.value = res;
  877. nodeTableData.value = [res];
  878. };
  879. //当前项目信息表
  880. const infoTableLoading = ref(false);
  881. const infoTableColumn = ref([
  882. { key: "tableName", name: "表单名称" },
  883. { key: "elementTotal", name: "字段总量", align: "center", width: 80 },
  884. { key: "fillRate", name: "填报率", align: "center", width: 80 },
  885. { key: "tableType", name: "表单类型", align: "center", width: 100 },
  886. { key: "tableOwner", name: "所属方", align: "center", width: 100 },
  887. { key: "action", name: "操作", align: "center", width: 160 },
  888. ]);
  889. const infoTableData = ref([]);
  890. const getInfoTableData = async () => {
  891. const { id } = treeItem.value;
  892. infoTableLoading.value = true;
  893. const { data } = await mainApi.findNodeTableByCondition({
  894. parentId: id,
  895. wbsId: wbsId.value,
  896. projectId: projectInfo.value.id,
  897. });
  898. infoTableData.value = getArrValue(data);
  899. infoTableLoading.value = false;
  900. };
  901. //当前项目信息表删除
  902. const delInfoTableRow = async ({ item }, resolve) => {
  903. const { isRes } = await mainApi.removeTableByCondition({
  904. id: item.id,
  905. wbsId: wbsId.value,
  906. projectId: projectInfo.value.id,
  907. });
  908. resolve(); //关闭弹窗
  909. if (!isRes) return;
  910. window.$message.success("删除成功");
  911. getInfoTableData().then();
  912. };
  913. //表单设置
  914. const isFormSet = ref(true);
  915. const infoTableColumn1 = ref([
  916. { key: "tableName", name: "表单名称" },
  917. { key: "tableType", name: "表单类型", align: "center", width: 80 },
  918. { key: "fillRate", name: "填报率", align: "center", width: 80 },
  919. { key: "isLinkTable", name: "关联清表", align: "center", width: 80 },
  920. { key: "tableOwner", name: "所属方", align: "center", width: 100 },
  921. {
  922. key: "action",
  923. name: "操作",
  924. width: 490,
  925. align: "center",
  926. fixed: "right",
  927. },
  928. ]);
  929. const setIsFormSetValue = () => {
  930. isFormSet.value = !isFormSet.value;
  931. if (isFormSet.value) {
  932. getTreeDetail();
  933. }
  934. getInfoTableData();
  935. };
  936. //数据同步按钮菜单
  937. const dataSyncMenu = [
  938. { key: "jdSync", name: "节点参数同步", load: false },
  939. { key: "dqSync", name: "电签同步", load: false },
  940. { key: "gsSync", name: "公式同步", load: false },
  941. ];
  942. const dataSyncMenuClick = (item) => {
  943. let pid = treeItem.value.primaryKeyId
  944. ? treeItem.value.primaryKeyId
  945. : treeItem.value.pKeyId;
  946. const { key } = item;
  947. if (key === "jdSync") {
  948. //是否同步节点参数
  949. HcFirmMsg(
  950. {
  951. text: "是否同步节点参数?",
  952. loadingText: "数据同步中...",
  953. },
  954. async (resolve) => {
  955. const { isRes } = await mainApi.syncNodeParam({
  956. projectId: projectInfo.value.id,
  957. pKeyId: pid,
  958. });
  959. resolve(); //关闭弹窗
  960. if (!isRes) return;
  961. window.$message.success("同步成功");
  962. }
  963. );
  964. } else if (key === "dqSync") {
  965. //是否同步电签
  966. HcFirmMsg(
  967. {
  968. text: "是否同步电签?",
  969. loadingText: "数据同步中...",
  970. },
  971. async (resolve) => {
  972. const { isRes } = await mainApi.syncProjecteVisa({
  973. projectId: projectInfo.value.id,
  974. pKeyId: pid,
  975. });
  976. resolve(); //关闭弹窗
  977. if (!isRes) return;
  978. window.$message.success("同步成功");
  979. }
  980. );
  981. } else if (key === "gsSync") {
  982. window.$message.success("暂无接口");
  983. }
  984. };
  985. // 关联清表
  986. const isAssociationShow = ref(false);
  987. const associationInfo = ref({});
  988. const associationList = async (item) => {
  989. associationInfo.value = item;
  990. await nextTick();
  991. isAssociationShow.value = true;
  992. };
  993. //编辑元素
  994. const isEditElementShow = ref(false);
  995. const editElementInfo = ref({});
  996. const editElementData = ref({});
  997. const editElementLoading = ref(false);
  998. const editElement = async (row) => {
  999. editElementLoading.value = true;
  1000. const { code, data } = await excelApi.getExcelHtml({ pkeyId: row.pkeyId });
  1001. if (code !== 200 || isNullES(data)) {
  1002. editElementLoading.value = false;
  1003. window?.$message.warning("表单异常,请联系管理员");
  1004. return;
  1005. }
  1006. editElementLoading.value = false;
  1007. editElementInfo.value = row;
  1008. editElementData.value = {
  1009. pid: projectInfo.value.id,
  1010. wbsid: wbsId.value,
  1011. nodeid: treeItem.value.id,
  1012. };
  1013. await nextTick();
  1014. isEditElementShow.value = true;
  1015. };
  1016. //调整表单
  1017. const isAdjustExcelShow = ref(false);
  1018. const adjustExcelLoading = ref(false);
  1019. const adjustExcelInfo = ref({});
  1020. const adjustExcelClick = async (row) => {
  1021. const { pkeyId, excelId } = row;
  1022. if (isNullES(pkeyId) || isNullES(excelId)) {
  1023. window?.$message.warning("表单值异常,请联系管理员");
  1024. return;
  1025. }
  1026. adjustExcelLoading.value = true;
  1027. const { code, data } = await excelApi.getExcelHtml({ pkeyId });
  1028. if (code !== 200 || isNullES(data)) {
  1029. adjustExcelLoading.value = false;
  1030. window?.$message.warning("表单异常,请联系管理员");
  1031. return;
  1032. }
  1033. adjustExcelInfo.value = deepClone(row);
  1034. adjustExcelLoading.value = false;
  1035. isAdjustExcelShow.value = true;
  1036. };
  1037. //编辑元素里的跳转页面
  1038. const editElementToPage = async (name) => {
  1039. const row = deepClone(editElementInfo.value);
  1040. //表单调整
  1041. if (name === "adjustment") {
  1042. adjustExcelInfo.value = deepClone(row);
  1043. await nextTick();
  1044. isAdjustExcelShow.value = true;
  1045. }
  1046. //公式配置
  1047. if (name === "formula") {
  1048. console.log("还没做");
  1049. }
  1050. };
  1051. //编辑元素公式
  1052. const elementFormulasName = ref("");
  1053. const elementFormulasObj = ref({});
  1054. const elementFormulasShow = ref(false);
  1055. const elementFormulasClick = async (row) => {
  1056. elementFormulasObj.value = row;
  1057. elementFormulasName.value = row.tableName + " 元素公式";
  1058. elementFormulasShow.value = true;
  1059. formulaTableLoading.value = true;
  1060. const { data } = await wbsTreeApi.selectFormElements({
  1061. id: row.pkeyId,
  1062. type: 0,
  1063. });
  1064. const arr = getArrValue(data);
  1065. formulaTableData.value = arr;
  1066. formulaTableList.value = deepClone(arr);
  1067. formulaTableLoading.value = false;
  1068. };
  1069. //元素公式列表
  1070. const formulaTableLoading = ref(false);
  1071. const formulaTableColumn = [
  1072. { key: "eName", name: "字段信息" },
  1073. { key: "action", name: "操作", width: 160, align: "center" },
  1074. ];
  1075. const formulaTableData = ref([]);
  1076. const formulaTableList = ref([]);
  1077. // 搜索元素公式
  1078. const formulaInput = ref("");
  1079. const searchFormulaClick = () => {
  1080. const arr = formulaTableList.value;
  1081. formulaTableData.value = arr.filter(({ eName }) => {
  1082. return eName.indexOf(formulaInput.value) > -1;
  1083. });
  1084. };
  1085. //编辑元素公式关闭
  1086. const elementFormulasClose = () => {
  1087. elementFormulasShow.value = false;
  1088. formulaTableLoading.value = false;
  1089. elementFormulasName.value = "";
  1090. formulaTableData.value = [];
  1091. formulaTableList.value = [];
  1092. };
  1093. //编辑公式
  1094. const isEditFormulaShow = ref(false);
  1095. const editFormulaData = ref({});
  1096. //全局公式,10
  1097. const toFormulaGlobal = async (row) => {
  1098. elementFormulasClose();
  1099. const formulasObj = elementFormulasObj.value;
  1100. formulasObj.hasPartFormula = row.hasPartFormula;
  1101. editFormulaData.value = {
  1102. node: formulasObj,
  1103. pid: projectInfo.value.id,
  1104. wbsId: wbsId.value,
  1105. nodeId: treeItem.value.id,
  1106. eleId: row.id,
  1107. eleType: false,
  1108. tableType: true,
  1109. globalType: 10,
  1110. };
  1111. await nextTick();
  1112. isEditFormulaShow.value = true;
  1113. };
  1114. //节点公式,20
  1115. const toFormulaNodes = async (row) => {
  1116. elementFormulasClose();
  1117. editFormulaData.value = {
  1118. node: treeItem.value,
  1119. pid: projectInfo.value.id,
  1120. wbsId: wbsId.value,
  1121. nodeId: treeItem.value.id,
  1122. eleId: row.id,
  1123. tableType: false,
  1124. globalType: 20,
  1125. };
  1126. await nextTick();
  1127. isEditFormulaShow.value = true;
  1128. };
  1129. //公式操作完成
  1130. const editFormulaFinish = () => {
  1131. isEditFormulaShow.value = false;
  1132. editFormulaData.value = {};
  1133. };
  1134. //离开了当前页面
  1135. onDeactivated(() => {
  1136. isAdjustExcelShow.value = false;
  1137. });
  1138. //节点参数
  1139. const nodeParamShow = ref(false);
  1140. const nodeParamClose = () => {
  1141. nodeParamShow.value = false;
  1142. };
  1143. const nodeParamClick = () => {
  1144. const { id } = treeItem.value;
  1145. if (!id) {
  1146. window?.$message.warning("请先选择节点");
  1147. return;
  1148. }
  1149. nodeParamShow.value = true;
  1150. };
  1151. //独立表单库
  1152. const independentShow = ref(false);
  1153. const independentClose = () => {
  1154. independentShow.value = false;
  1155. };
  1156. const toIndependent = () => {
  1157. independentShow.value = true;
  1158. };
  1159. //归档文件时间
  1160. const isArchiveShow = ref(false);
  1161. const archiveClick = () => {
  1162. isArchiveShow.value = true;
  1163. };
  1164. //编辑元素表单
  1165. const editEleShow = ref(false);
  1166. const editClose = () => {
  1167. editEleShow.value = false;
  1168. };
  1169. const editRowClick = (row) => {
  1170. editEleShow.value = true;
  1171. };
  1172. // 元素表排序
  1173. const tableSortShow = ref(false);
  1174. const sortClick = () => {
  1175. tableSortShow.value = true;
  1176. };
  1177. const tableSortShowClose = () => {
  1178. tableSortShow.value = false;
  1179. getInfoTableData();
  1180. };
  1181. //预览
  1182. const previewShow = ref(false);
  1183. const previewInfo = ref({});
  1184. const previewClick = (row) => {
  1185. previewShow.value = true;
  1186. previewInfo.value = row;
  1187. };
  1188. //创建新的元素表
  1189. const isCreateShow = ref(false);
  1190. const modalTitle = ref("创建新的元素表");
  1191. const createClose = () => {
  1192. isCreateShow.value = false;
  1193. getInfoTableData();
  1194. };
  1195. const initTableName = ref("");
  1196. const initTableId = ref("");
  1197. const eKey = ref("");
  1198. const tableId = ref("");
  1199. const handleEdit = (row) => {
  1200. isCreateShow.value = true;
  1201. modalTitle.value = row.tableName + "元素编辑";
  1202. tableId.value = row.pkeyId;
  1203. initTableName.value = row.initTableName;
  1204. initTableId.value = row.initTableId;
  1205. eKey.value = row.ekey;
  1206. };
  1207. //隐藏表单
  1208. const hideClick = async (row) => {
  1209. //隐藏按钮
  1210. const { code, error } = await wbsTreeApi.updateStatus({
  1211. pKeyId: row.pkeyId,
  1212. });
  1213. if (!error && code === 200) {
  1214. if (row.status == 0) {
  1215. row.status = 1;
  1216. } else {
  1217. row.status = 0;
  1218. }
  1219. }
  1220. };
  1221. //表单同步
  1222. const syncTableLoading = ref(false);
  1223. const syncTable = async (row) => {
  1224. syncTableLoading.value = true;
  1225. const { code, error } = await wbsTreeApi.syncCurrentFormInProject({
  1226. pKeyId: row.pkeyId,
  1227. });
  1228. syncTableLoading.value = false;
  1229. if (!error && code === 200) {
  1230. window?.$message.success("操作成功");
  1231. }
  1232. };
  1233. //关联节点
  1234. const isAllocateShow = ref(false);
  1235. const allocateWbsInfo = ref({});
  1236. const linkNodeClick = (row) => {
  1237. allocateWbsInfo.value = row;
  1238. isAllocateShow.value = true;
  1239. };
  1240. </script>
  1241. <style scoped lang="scss">
  1242. .hc-project-wbs-tree {
  1243. position: relative;
  1244. background: #ececec;
  1245. border-radius: 4px;
  1246. height: 100%;
  1247. flex-direction: column;
  1248. overflow: hidden;
  1249. .header {
  1250. color: white;
  1251. background: #54565a;
  1252. padding: 10px 14px;
  1253. flex-shrink: 0;
  1254. .name {
  1255. white-space: nowrap;
  1256. overflow: hidden;
  1257. text-overflow: ellipsis;
  1258. }
  1259. }
  1260. .body {
  1261. flex: 1;
  1262. flex-basis: auto;
  1263. position: relative;
  1264. }
  1265. }
  1266. </style>
  1267. <style lang="scss">
  1268. .hc-project-wbs-tree .body {
  1269. .el-card.hc-card-box {
  1270. --el-card-padding: 12px;
  1271. --el-card-border-radius: 5px;
  1272. }
  1273. .hc-page-split-content {
  1274. position: relative;
  1275. .body-top {
  1276. position: relative;
  1277. height: 119.5px;
  1278. }
  1279. .body-content {
  1280. position: relative;
  1281. margin-top: 10px;
  1282. height: calc(100% - 129.5px);
  1283. }
  1284. }
  1285. }
  1286. </style>