wbs.vue 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452
  1. <template>
  2. <div class="h-full">
  3. <HcCard id-ref="wbs-node-tree-card-target" v-if="wbsTypeTabKey === 'map'">
  4. <template #header>
  5. <HcTooltip keys="wbs_views_division">
  6. <el-button type="primary" hc-btn @click="divisionClick">
  7. <HcIcon name="node-tree" :line="false"/>
  8. <span>划分变更</span>
  9. </el-button>
  10. </HcTooltip>
  11. <HcTooltip keys="wbs_views_drawings" v-if="isDrawer">
  12. <el-button hc-btn :disabled="!nodeDataInfo?.fileUrl" @click="viewsDrawings">
  13. <HcIcon name="image"/>
  14. <span>查看图纸</span>
  15. </el-button>
  16. </HcTooltip>
  17. <el-button :type="authBtnTabKey === '1'?'primary':''" hc-btn @click="authBtnTabClick('1')" v-if="isDrawer">
  18. <HcIcon name="folder-user"/>
  19. <span>施工自检</span>
  20. </el-button>
  21. <el-button :type="authBtnTabKey === '2'?'primary':''" hc-btn @click="authBtnTabClick('2')" v-if="isDrawer">
  22. <HcIcon name="folder-shield"/>
  23. <span>监理质检</span>
  24. </el-button>
  25. </template>
  26. <template #extra>
  27. <HcNewSwitch :datas="wbsTypeTab" :keys="wbsTypeTabKey" @change="wbsTypeTabChange"/>
  28. </template>
  29. <NodeTree ref="NodeTreeRef" :autoExpandKeys="TreeAutoExpandKeys" :menus="ElTreeMenu" :isMark="TreeMark" :projectId="projectId" :contractId="contractId"
  30. :accordion='NodeTreeAccordion' @nodeClick="NodeTreeClick" @nodeDblClick="NodeTreeDblClick" @menuClick="NodeTreeMenuClick"/>
  31. <template #action>
  32. <div class="hc-tree-mp-tip-box">
  33. <div class="dot-view green">已审批</div>
  34. <div class="dot-view black">未填报</div>
  35. <div class="dot-view orange">已填报-待审批</div>
  36. <div class="dot-view blue">已填报-未上报</div>
  37. </div>
  38. </template>
  39. <HcDrawer :show="isDrawer" actionUi="text-center" to-id="wbs-node-tree-card-target" @close="drawerClose">
  40. <!--清表列表-->
  41. <el-scrollbar ref="ListItemScrollRef" v-if="ListItemDatas.length > 0">
  42. <ListItem ref="ListItemsRef"
  43. :datas="ListItemDatas"
  44. :status="NodeStatus"
  45. :classify="authBtnTabKey"
  46. @offsetTop="ListItemOffsetTop"
  47. :projectInfo="projectInfo"
  48. :primaryKeyId="primaryKeyId"
  49. :contractId="contractId"
  50. @renew="getTableDataAll"
  51. :drawType="isDrawType"
  52. />
  53. </el-scrollbar>
  54. <HcStatus text="暂无表单" v-else/>
  55. <!--底部按钮区域-->
  56. <template #action>
  57. <HcTooltip keys="wbs_save" v-if="NodeStatus !== '3'">
  58. <el-button type="primary" hc-btn :disabled="NodeStatus === '3' || ListItemDatas.length <= 0" :loading="tableFormSaveLoading" @click="tableFormSaveClick">
  59. <HcIcon name="save"/>
  60. <span>保存</span>
  61. </el-button>
  62. </HcTooltip>
  63. <HcTooltip keys="wbs_report" v-if="NodeStatus !== '3'">
  64. <el-button hc-btn :disabled="NodeStatus === '3' || NodeStatus === '1'" :loading="reportLoading" @click="reportModalClick">
  65. <HcIcon name="send-plane-2"/>
  66. <span>上报</span>
  67. </el-button>
  68. </HcTooltip>
  69. <HcTooltip keys="wbs_preview">
  70. <el-button hc-btn :disabled="NodeStatus === '1'" :loading="bussPdfsLoading" @click="bussPdfsClick">
  71. <HcIcon name="eye"/>
  72. <span>预览</span>
  73. </el-button>
  74. </HcTooltip>
  75. <HcTooltip keys="wbs_abolish" v-if="NodeStatus === '3'">
  76. <el-button hc-btn @click="abolishOneClick">
  77. <HcIcon name="arrow-go-back"/>
  78. <span>撤回上报流程</span>
  79. </el-button>
  80. </HcTooltip>
  81. <el-button hc-btn @click="drawerClose">
  82. <HcIcon name="close"/>
  83. <span>关闭填报页面</span>
  84. </el-button>
  85. </template>
  86. </HcDrawer>
  87. </HcCard>
  88. <div class="hc-layout-box" v-if="wbsTypeTabKey === 'tree'">
  89. <div class="hc-layout-left-box" id="wbs-left-tree" :style="'width:' + leftWidth + 'px;'">
  90. <div class="hc-project-box">
  91. <div class="hc-project-icon-box">
  92. <HcIcon name="stack"/>
  93. </div>
  94. <div class="ml-2 project-name-box">
  95. <span class="text-xl text-cut project-alias">{{projectInfo['projectAlias']}}</span>
  96. <div class="text-xs text-cut project-name">{{projectInfo['name']}}</div>
  97. </div>
  98. </div>
  99. <div class="hc-tree-box">
  100. <div class="hc-search-tree-val">
  101. <el-input v-model="searchTreeVal" block size="large" placeholder="请输入名称关键词检索" clearable @keyup="searchTreeKeyUp">
  102. <template #suffix>
  103. <HcIcon name="search-2" ui="text-xl" @click="searchTreeClick"/>
  104. </template>
  105. </el-input>
  106. </div>
  107. <div class="hc-tree-scrollbar" v-loading="treeLoading" element-loading-text="获取数据中...">
  108. <el-scrollbar>
  109. <KeepAlive>
  110. <template v-if="isSearchTree">
  111. <HcTreeData
  112. :datas="searchTreeData"
  113. :menus="ElTreeMenu"
  114. :isMark="TreeMark"
  115. :autoExpandKeys="TreeAutoExpandKeys"
  116. :searchTreeVal="searchTreeVal" i
  117. sColor @nodeTap="wbsElTreeClick"
  118. @menuTap="ElTreeMenuClick"
  119. @changeSearch="changeisSearch"
  120. :submitCounts="false"
  121. />
  122. </template>
  123. <template v-else>
  124. <WbsTree :submitCounts="false" :menus="ElTreeMenu" :isMark="TreeMark" :autoExpandKeys="TreeAutoExpandKeys" :projectId="projectId" :contractId="contractId" isColor @nodeTap="wbsElTreeClick" @menuTap="ElTreeMenuClick" @nodeLoading="ElTreeNodeLoading" />
  125. </template>
  126. </KeepAlive>
  127. </el-scrollbar>
  128. </div>
  129. </div>
  130. <div class="hc-tree-foot-tip-box">
  131. <div class="dot-view green">已审批</div>
  132. <div class="dot-view black">未填报</div>
  133. <div class="dot-view orange">已填报-待审批</div>
  134. <div class="dot-view blue">已填报-未上报</div>
  135. </div>
  136. <!--左右拖动-->
  137. <div class="horizontal-drag-line" @mousedown="onmousedown"/>
  138. </div>
  139. <div class="hc-layout-content-box">
  140. <HcCard actionUi="text-center">
  141. <template #header>
  142. <HcTooltip keys="wbs_views_drawings">
  143. <el-button hc-btn :disabled="!nodeDataInfo?.fileUrl" @click="viewsDrawings">
  144. <HcIcon name="image"/>
  145. <span>查看图纸</span>
  146. </el-button>
  147. </HcTooltip>
  148. <el-button :type="authBtnTabKey === '1'?'primary':''" hc-btn @click="authBtnTabClick('1')">
  149. <HcIcon name="folder-user"/>
  150. <span>施工自检</span>
  151. </el-button>
  152. <el-button :type="authBtnTabKey === '2'?'primary':''" hc-btn @click="authBtnTabClick('2')">
  153. <HcIcon name="folder-shield"/>
  154. <span>监理质检</span>
  155. </el-button>
  156. </template>
  157. <!--切换导图或树形模式-->
  158. <template #extra>
  159. <HcNewSwitch :datas="wbsTypeTab" :keys="wbsTypeTabKey" @change="wbsTypeTabChange"/>
  160. </template>
  161. <!--清表列表-->
  162. <el-scrollbar ref="ListItemScrollRef" v-loading="ListItemLoading" v-if="ListItemDatas.length > 0">
  163. <ListItem
  164. ref="ListItemRef"
  165. :datas="ListItemDatas"
  166. :status="NodeStatus"
  167. :classify="authBtnTabKey"
  168. :authBtnTabKey="authBtnTabKey"
  169. @offsetTop="ListItemOffsetTop"
  170. :projectInfo="projectInfo"
  171. :primaryKeyId="primaryKeyId"
  172. :contractId="contractId"
  173. @renew="getTableDataAll"
  174. :drawType="!isDrawType"
  175. :wbsTempId="projectInfo?.referenceWbsTemplateIdTrial" :wbsType="2" :tenantId="userInfo?.tenant_id"
  176. />
  177. </el-scrollbar>
  178. <HcStatus text="暂无表单" v-else/>
  179. <!--底部按钮区域-->
  180. <template #action>
  181. <HcTooltip keys="wbs_save" v-if="NodeStatus !== '3'">
  182. <el-button type="primary" hc-btn :disabled="NodeStatus === '3' || ListItemDatas.length <= 0" :loading="tableFormSaveLoading" @click="tableFormSaveClick">
  183. <HcIcon name="save"/>
  184. <span>保存</span>
  185. </el-button>
  186. </HcTooltip>
  187. <HcTooltip keys="wbs_report" v-if="NodeStatus !== '3'">
  188. <el-button hc-btn :disabled="NodeStatus === '3' || NodeStatus === '1'" :loading="reportLoading" @click="reportModalClick">
  189. <HcIcon name="send-plane-2"/>
  190. <span>上报</span>
  191. </el-button>
  192. </HcTooltip>
  193. <HcTooltip keys="wbs_preview">
  194. <el-button hc-btn :disabled="NodeStatus === '1'" :loading="bussPdfsLoading" @click="bussPdfsClick">
  195. <HcIcon name="eye"/>
  196. <span>预览</span>
  197. </el-button>
  198. </HcTooltip>
  199. <HcTooltip keys="wbs_abolish" v-if="NodeStatus === '3'">
  200. <el-button hc-btn @click="abolishOneClick">
  201. <HcIcon name="arrow-go-back"/>
  202. <span>撤回上报流程</span>
  203. </el-button>
  204. </HcTooltip>
  205. </template>
  206. </HcCard>
  207. </div>
  208. </div>
  209. <!--上传图纸-->
  210. <div class="upload-drawing">
  211. <el-upload :action="action" :accept="accept" :headers="getTokenHeader()" :before-upload="beforeUpload" :on-success="uploadFinish" :on-error="uploadError">
  212. <div id="upload-drawing">上传图纸</div>
  213. </el-upload>
  214. </div>
  215. <!--查看图纸-->
  216. <HcDragModal title="查看图纸" ui="hc-image-preview-box" :isShow="drawingsShow" closeIcon tops="100" lefts="145" widths="380px" @close="drawingsClose">
  217. <div class="hc-image-preview-view">
  218. <el-image-viewer :url-list="[nodeDataInfo.fileUrl]"/>
  219. </div>
  220. </HcDragModal>
  221. <!--编辑节点-->
  222. <HcDialog :show="editNodeModal" title="编辑节点" widths="600px" :loading="editNodeLoading" @close="editNodeModal = false" @save="editNodeClick">
  223. <el-form ref="formEditNodeRef" :model="formEditNodeModel" :rules="formEditNodeRules" label-width="auto" size="large">
  224. <el-form-item label="节点名称" prop="title">
  225. <el-input v-model="formEditNodeModel.title" placeholder="请输入节点名称"/>
  226. </el-form-item>
  227. <el-form-item label="上级节点">
  228. <el-input v-model="formEditNodeModel.parent.title" disabled/>
  229. </el-form-item>
  230. <el-form-item label="节点类型">
  231. <el-select v-model="formEditNodeModel.type" block disabled>
  232. <el-option v-for="item in nodeTypeData" :label="item.label" :value="item.value"/>
  233. </el-select>
  234. </el-form-item>
  235. <el-form-item label="划分编号">
  236. <el-input v-model="formEditNodeModel.partitionCode" placeholder="请输入划分编号"/>
  237. </el-form-item>
  238. <!-- <el-form-item label="模板位置">
  239. <el-input v-model="formEditNodeModel.position" id="copyText">
  240. <template #append>
  241. <el-button :icon="DocumentCopy" @click="copyText"/>
  242. </template>
  243. </el-input>
  244. </el-form-item> -->
  245. </el-form>
  246. </HcDialog>
  247. <!--复制节点-->
  248. <HcDialog :show="copyNodeModal" title="复制节点" :widths="copyNodeTabKey === '1'?'600px':'1200px'" @close="copyNodeModal = false">
  249. <el-form ref="formCopyNodeModelRef" :model="formCopyNodeModel" :rules="formCopyNodeModelRules" label-width="auto" size="large" v-if="copyNodeTabKey !== '3'">
  250. <el-form-item label="节点名称" prop="title" style="margin-bottom: 0;">
  251. <el-input v-model="formCopyNodeModel.title" placeholder="请输入节点名称"/>
  252. </el-form-item>
  253. </el-form>
  254. <div class="copy-node-many-box" v-if="copyNodeTabKey !== '1'">
  255. <div class="copy-node-many-tree">
  256. <el-scrollbar>
  257. <WbsTree :autoExpandKeys="TreeAutoExpandKeys" :projectId="projectId" :contractId="contractId" idPrefix="tree-node-copy-" :isAutoClick="false" :isAutoKeys="false" @nodeTap="copyNodeElTreeClick"/>
  258. </el-scrollbar>
  259. </div>
  260. <div class="copy-node-many-table">
  261. <el-scrollbar>
  262. <el-table :data="copyNodeTable" border stripe>
  263. <el-table-column prop="title" label="复制到的位置"/>
  264. <el-table-column prop="nodeName" label="节点名称" v-if="copyNodeTabKey === '2'">
  265. <template #default="{row}">
  266. <el-form ref="copyNodeTableRef" :model="row" :rules="copyNodeTableRules" label-width="0" size="large">
  267. <el-form-item prop="nodeName" style="margin-bottom: 0;">
  268. <el-input v-model="row.nodeName" placeholder="请输入节点名称"/>
  269. </el-form-item>
  270. </el-form>
  271. </template>
  272. </el-table-column>
  273. <el-table-column prop="action" label="操作" width="120" align="center">
  274. <template #default="{_,$index}">
  275. <el-button type="danger" plain @click="copyNodeTableDel($index)">删除</el-button>
  276. </template>
  277. </el-table-column>
  278. </el-table>
  279. </el-scrollbar>
  280. </div>
  281. </div>
  282. <template #footer>
  283. <div class="lr-dialog-footer">
  284. <div class="left">
  285. <template v-for="item in copyNodeTab">
  286. <el-button size="large" type="primary" plain v-if="item?.key === copyNodeTabKey" @click="copyNodeTabChange(item?.key)">{{item.name}}</el-button>
  287. <el-button size="large" text bg @click="copyNodeTabChange(item?.key)" v-else>{{item.name}}</el-button>
  288. </template>
  289. </div>
  290. <div class="right">
  291. <el-button size="large" @click="copyNodeModal = false">取消</el-button>
  292. <el-button type="primary" hc-btn :loading="copyNodeLoading" @click="copyNodeClick">提交</el-button>
  293. </div>
  294. </div>
  295. </template>
  296. </HcDialog>
  297. <!--新增子节点-->
  298. <HcDialog :show="addNodeModal" title="新增子节点" widths="720px" @close="addNodeModal = false">
  299. <el-alert title="双击节点,可编辑节点名称,编辑完成后,请按回车或输入框消失后,再点提交" type="warning" :closable="false"/>
  300. <HcTreeNode :projectId="projectId" :nodeId="addTreeNodeId" :oldId="addTreeNodeOldId" @check-change="addTreeNodeCheckChange" v-if="addTreeNodeType === '1'"/>
  301. <HcTreeNode :projectId="projectId" :nodeId="addTreeNodeId" :oldId="addTreeNodeOldId" strictly @check-change="addTreeNodeCheckChange" v-if="addTreeNodeType === '2'"/>
  302. <template #footer>
  303. <div class="lr-dialog-footer">
  304. <div class="left flex items-center">
  305. <div class="mr-4">选中方式:</div>
  306. <el-radio-group v-model="addTreeNodeType">
  307. <el-radio label="1">当前及子节点</el-radio>
  308. <el-radio label="2" class="ml-4">仅当前节点</el-radio>
  309. </el-radio-group>
  310. </div>
  311. <div class="right">
  312. <el-button size="large" @click="addNodeModal = false">取消</el-button>
  313. <el-button type="primary" hc-btn :loading="addNodeLoading" @click="addNodeClick">提交</el-button>
  314. </div>
  315. </div>
  316. </template>
  317. </HcDialog>
  318. <!--调整排序-->
  319. <HcDialog :show="sortNodeModal" title="调整排序" widths="700px" :loading="sortNodeLoading" @close="sortNodeModal = false" @save="sortNodeClick">
  320. <el-alert title="可拖动排序,也可在后面点击图标,切换排序" type="warning" :closable="false"/>
  321. <div class="sort-node-body-box list-group header">
  322. <div class="list-group-item">
  323. <div class="index-box">序号</div>
  324. <div class="title-box">节点名称</div>
  325. <div class="icon-box">排序</div>
  326. </div>
  327. </div>
  328. <Draggable class="sort-node-body-box list-group" ghost-class="ghost" :list="sortNodeData" item-key="id" @start="sortNodeDrag = true" @end="sortNodeDrag = false">
  329. <template #item="{element, index}">
  330. <div class="list-group-item">
  331. <div class="index-box">{{index + 1}}</div>
  332. <div class="title-box">{{element.title}}</div>
  333. <div class="icon-box">
  334. <span class="icon" @click="downSortClick(index)">
  335. <HcIcon name="arrow-down" ui="text-lg"/>
  336. </span>
  337. <span class="icon" @click="upSortClick(index)">
  338. <HcIcon name="arrow-up" ui="text-lg"/>
  339. </span>
  340. </div>
  341. </div>
  342. </template>
  343. </Draggable>
  344. </HcDialog>
  345. <!--批量上报审批-->
  346. <HcReportModal title="批量上报审批" url="informationWriteQuery/taskOne" :show="showReportModal" :projectId="projectId" :contractId="contractId" type="wbs" :typeData="reportTypeData"
  347. :taskName="reportTaskName" :ids="reportIds" :addition="reportAddition" @hide="showReportModal = false" @finish="showReportFinish"/>
  348. </div>
  349. </template>
  350. <script setup>
  351. import { DocumentCopy } from '@element-plus/icons-vue'
  352. import {ref,watch,onMounted} from "vue";
  353. import {useRouter, useRoute} from 'vue-router'
  354. import {useAppStore} from "~src/store";
  355. import {HcIsButton} from "~src/plugins/IsButtons";
  356. import ListItem from "./components/ListItem.vue"
  357. import NodeTree from "./components/nodeTree/index.vue"
  358. import HcTreeNode from "./components/HcTreeNode.vue"
  359. import HcTreeData from "./components/HcTreeData.vue"
  360. import WbsTree from "./components/WbsTree.vue"
  361. import {getTokenHeader} from '~src/api/request/header';
  362. import {getStoreData, setStoreData} from '~src/utils/storage'
  363. import {isType, deepClone, formValidate} from "vue-utils-plus"
  364. import {getDictionary, eVisaTaskCheckApi} from "~api/other"
  365. import wbsApi from "~api/data-fill/wbs"
  366. import queryApi from '~api/data-fill/query';
  367. import Draggable from "vuedraggable";
  368. //初始变量
  369. const router = useRouter()
  370. const useRoutes = useRoute()
  371. const useAppState = useAppStore()
  372. const {getObjValue, getArrValue, getObjNullValue, isString} = isType()
  373. //全局变量
  374. const projectId = ref(useAppState.getProjectId);
  375. const contractId = ref(useAppState.getContractId);
  376. const projectInfo = ref(useAppState.getProjectInfo);
  377. const contractInfo = ref(useAppState.getContractInfo);
  378. const isCollapse = ref(useAppState.getCollapse)
  379. const userInfo = ref(useAppState.getUserInfo);
  380. //路由参数
  381. const routerQuery = useRoutes?.query;
  382. const typeName = routerQuery?.type || 'map'
  383. //是否是抽屉
  384. const isDrawType = ref(true)
  385. //自动展开缓存
  386. const TreeAutoExpandKeys = ref(getStoreData('wbsTreeExpandKeys') || [])
  387. //树搜索
  388. const isSearchTree = ref(false)
  389. const getSearchTreeData=async()=>{
  390. const {error, code, data} = await queryApi.getTreeall({
  391. contractId: contractId.value,
  392. projectId: projectId.value,
  393. wbsId:projectInfo?.value.referenceWbsTemplateId
  394. })
  395. //判断状态
  396. if (!error && code === 200) {
  397. searchTreeData.value = getArrValue(data)
  398. treeLoading.value = false
  399. } else {
  400. treeLoading.value = false
  401. searchTreeData.value = []
  402. }
  403. }
  404. //监听
  405. watch(() => [
  406. useAppState.getCollapse,
  407. ], ([Collapse]) => {
  408. isCollapse.value = Collapse
  409. })
  410. watch(projectId, (val) => {
  411. console.log(val,'val')
  412. if(val){
  413. getSearchTreeData()
  414. }
  415. },
  416. {immediate:true}
  417. )
  418. //渲染完成
  419. onMounted(()=> {
  420. treeLoading.value = typeName === 'tree';
  421. setContractType(contractInfo.value?.contractType)
  422. getDictionaryApi()
  423. })
  424. //身份按钮切换数据
  425. const authBtnTabKey = ref('1')
  426. const authBtnTabClick = (val) => {
  427. if (!primaryKeyId.value) {
  428. window?.$message?.warning('请先在左侧项目树选择一个节点')
  429. } else if (val !== authBtnTabKey.value) {
  430. authBtnTabKey.value = val
  431. getTableDataAll()
  432. }
  433. }
  434. //contractType, 1施工,2监理
  435. const setContractType = (contractType) => {
  436. if (contractType <= 0) {
  437. authBtnTabKey.value = '1'
  438. } else {
  439. authBtnTabKey.value = contractType + ''
  440. }
  441. setElTreeMenu(contractType)
  442. }
  443. const getTableDataAll = () => {
  444. searchNodeAllTable()
  445. queryNodeStatus()
  446. }
  447. //结构类型tab数据和相关处理
  448. const wbsTypeTabKey = ref(typeName)
  449. const wbsTypeTab = ref([
  450. {key:'map', name: '导图结构填报'},
  451. {key:'tree', name: '树形结构填报'}
  452. ]);
  453. const wbsTypeTabChange = (item) => {
  454. wbsTypeTabKey.value = item?.key;
  455. ListItemDatas.value = []
  456. isDrawer.value = false;
  457. treeLoading.value = typeName === 'tree';
  458. //路由跳转
  459. router.push({
  460. path: useRoutes.path,
  461. query: {
  462. type: item?.key
  463. }
  464. })
  465. getSearchTreeData()
  466. }
  467. //上传文件的
  468. const action = ref("/api/blade-resource/oss/endpoint/put-file")
  469. const accept = ref("image/png,image/jpg,image/jpeg")
  470. const NodeTreeAccordion = ref(true)
  471. //设置树菜单数据
  472. const ElTreeMenu = ref([])
  473. const TreeMark = ref(false)
  474. const setElTreeMenu = (contractType) => {
  475. let newArr = [];
  476. if (contractType === 1) {
  477. if (HcIsButton('wbs_tree_edit')) {
  478. newArr.push({icon: 'draft', label: '编辑节点', key: "edit"})
  479. }
  480. if (HcIsButton('wbs_tree_mark')) {
  481. newArr.push({icon: 'star', label: '标记为首件', key: "mark"})
  482. TreeMark.value = true
  483. }
  484. if (HcIsButton('wbs_tree_copy')) {
  485. newArr.push({icon: 'file-copy-2', label: '复制节点', key: "copy"})
  486. }
  487. if (HcIsButton('wbs_tree_add')) {
  488. newArr.push({icon: 'add-circle', label: '新增节点', key: "add"})
  489. }
  490. if (HcIsButton('wbs_tree_upload')) {
  491. newArr.push({icon: 'file-upload', label: '上传图纸', key: "upload"})
  492. }
  493. if (HcIsButton('wbs_tree_del')) {
  494. newArr.push({icon: 'delete-bin', label: '删除节点', key: "del"})
  495. }
  496. if (HcIsButton('wbs_tree_sort')) {
  497. newArr.push({icon: 'sort-asc', label: '调整排序', key: "sort"})
  498. }
  499. } else if (contractType === 2) {
  500. if (HcIsButton('wbs_tree_copy')) {
  501. newArr.push({icon: 'file-copy-2', label: '复制节点', key: "copy"})
  502. }
  503. if (HcIsButton('wbs_tree_add')) {
  504. newArr.push({icon: 'add-circle', label: '新增节点', key: "add"})
  505. }
  506. }
  507. ElTreeMenu.value = newArr
  508. }
  509. //树相关变量
  510. const primaryKeyId = ref('')
  511. const nodeItemInfo = ref({})
  512. const nodeDataInfo = ref({})
  513. const searchTreeVal = ref('')
  514. const searchTreeData = ref([])
  515. //回车
  516. const searchTreeKeyUp = (e) => {
  517. if (e.key === "Enter") {
  518. searchTreeClick()
  519. }
  520. }
  521. const changeisSearch=()=>{
  522. isSearchTree.value=false
  523. }
  524. const treeLoading = ref(false)
  525. const searchTreeClick = async () => {
  526. isSearchTree.value=true
  527. }
  528. // if (searchTreeVal.value) {
  529. // isSearchTree.value = true
  530. // treeLoading.value = true
  531. // const {error, code, data} = await wbsApi.searchContractTree({
  532. // contractId: contractId.value,
  533. // queryValue: searchTreeVal.value
  534. // })
  535. // //判断状态
  536. // if (!error && code === 200) {
  537. // searchTreeData.value = getArrValue(data)
  538. // treeLoading.value = false
  539. // } else {
  540. // treeLoading.value = false
  541. // searchTreeData.value = []
  542. // }
  543. // } else {
  544. // treeLoading.value = false
  545. // isSearchTree.value = false
  546. // }
  547. //树被点击
  548. const wbsElTreeClick = ({node, data, keys}) => {
  549. nodeItemInfo.value = node
  550. nodeDataInfo.value = data
  551. primaryKeyId.value = data?.primaryKeyId || ''
  552. setStoreData('wbsTreeExpandKeys',keys)
  553. TreeAutoExpandKeys.value = keys || []
  554. getTableDataAll()
  555. }
  556. //树加载完成
  557. const ElTreeNodeLoading = () => {
  558. treeLoading.value = false
  559. }
  560. //树菜单被点击
  561. const ElTreeMenuClick = async ({key,node,data,keys}) => {
  562. nodeItemInfo.value = node
  563. nodeDataInfo.value = data
  564. setStoreData('wbsTreeExpandKeys',keys)
  565. setTreeMenuDataClick({key,node,data})
  566. }
  567. //导图结构数据
  568. const NodeTreeRef = ref(null)
  569. //鼠标左键单击事件
  570. const NodeTreeClick = ({keys}) => {
  571. setStoreData('wbsTreeExpandKeys',keys)
  572. TreeAutoExpandKeys.value = keys || []
  573. }
  574. //双击事件
  575. const isDrawer = ref(false)
  576. const NodeTreeDblClick = ({node,data}) => {
  577. nodeItemInfo.value = node
  578. nodeDataInfo.value = data
  579. primaryKeyId.value = data?.primaryKeyId || ''
  580. isDrawer.value = true;
  581. getTableDataAll()
  582. }
  583. const drawerClose = () => {
  584. isDrawer.value = false;
  585. ListItemDatas.value = []
  586. }
  587. //导图树菜单被点击
  588. const NodeTreeMenuClick = async ({key,node,data}) => {
  589. nodeItemInfo.value = node
  590. nodeDataInfo.value = data
  591. setTreeMenuDataClick({key,node,data})
  592. }
  593. //处理菜单被点击数据
  594. const setTreeMenuDataClick = ({key,node,data}) => {
  595. const tabKey = wbsTypeTabKey.value
  596. if (key === 'mark' || key === 'cancel_mark') {
  597. firstItemBox()
  598. } else if (key === 'edit') {
  599. if (tabKey === 'tree') {
  600. const parent = deepClone(node?.parent?.data || {})
  601. formEditNodeModel.value = {...deepClone(data), parent: parent}
  602. } else if (tabKey === 'map') {
  603. const parent = deepClone(node?.parentNodes?.data || {})
  604. formEditNodeModel.value = {...deepClone(data), parent: parent}
  605. }
  606. editNodeModal.value = true
  607. } else if (key === 'copy') {
  608. if (tabKey === 'tree') {
  609. const parent = deepClone(node?.parent?.data || {})
  610. formCopyNodeModel.value = {...deepClone(data), parent: parent}
  611. } else if (tabKey === 'map') {
  612. const parent = deepClone(node?.parentNodes?.data || {})
  613. formCopyNodeModel.value = {...deepClone(data), parent: parent}
  614. }
  615. copyNodeTabKey.value = '1'
  616. copyNodeTable.value = []
  617. copyNodeLoading.value = false
  618. copyNodeModal.value = true
  619. } else if (key === 'add') {
  620. addTreeNodeId.value = data?.id
  621. addTreeNodeOldId.value = data?.oldId
  622. addNodeLoading.value = false
  623. addNodeModal.value = true
  624. } else if (key === 'upload') {
  625. document.getElementById('upload-drawing').click()
  626. } else if (key === 'del') {
  627. if(data['colorStatus']!==1){
  628. window?.$message?.warning('该节点已存在上报数据,不允许删除')
  629. }else{
  630. delModalClick()
  631. }
  632. } else if (key === 'sort') {
  633. let nodes = [], childNodes = []
  634. if (tabKey === 'tree') {
  635. childNodes = node?.parent?.childNodes || []
  636. } else if (tabKey === 'map') {
  637. childNodes = node?.parentNodes?.childrenNodes || []
  638. }
  639. for (let i = 0; i < childNodes.length; i++) {
  640. const res = childNodes[i]?.data
  641. nodes.push({
  642. id: res?.primaryKeyId,
  643. title: res?.title
  644. })
  645. }
  646. sortNodeData.value = nodes
  647. sortNodeModal.value = true
  648. }
  649. }
  650. //复制节点位置
  651. const copyText=()=> {
  652. let copyCon = document.getElementById("copyText");
  653. copyCon.select(); // 选中文本
  654. document.execCommand("copy"); // 执行浏览器复制命令
  655. window.$message?.success("复制成功!");
  656. }
  657. //上传前
  658. const loadingReactive = ref(null)
  659. const beforeUpload = () => {
  660. loadingReactive.value = window.$loading?.service({
  661. lock: true,
  662. text: '图纸上传中...',
  663. background: 'rgba(0, 0, 0, 0.7)',
  664. })
  665. return true
  666. }
  667. //上传完成
  668. const uploadFinish = async (response) => {
  669. const res = getObjValue(response.data)
  670. const info = nodeDataInfo.value;
  671. if (res?.link) {
  672. const { error, code, data } = await wbsApi.saveContractTreeDrawings({
  673. fileUrl: res?.link,
  674. id: info['drawingsId'],
  675. primaryKeyId: info['primaryKeyId']
  676. },false)
  677. //处理数据
  678. loadingReactive.value.close();
  679. if (!error && code === 200) {
  680. nodeDataInfo.value['drawingsId'] = data
  681. nodeDataInfo.value['fileUrl'] = res?.link
  682. window?.$message?.success('图纸上传成功')
  683. } else {
  684. window?.$message?.error('图纸保存失败')
  685. }
  686. } else {
  687. loadingReactive.value.close();
  688. window?.$message?.error('图纸上传失败')
  689. }
  690. }
  691. //上传失败
  692. const uploadError = () => {
  693. loadingReactive.value.close();
  694. window?.$message?.error('图纸上传失败')
  695. }
  696. //确认标记为首件
  697. const firstItemBox = () => {
  698. const info = nodeDataInfo.value;
  699. window?.$messageBox?.alert(`<div class="text-base font-bold">
  700. <span>请确认将</span>
  701. <span class="text-main">【${info['title']}】</span>
  702. <span>${info['isFirst']?'取消':''}标记为首件</span>
  703. </div>`, '标记首件制', {
  704. showCancelButton: true,
  705. dangerouslyUseHTMLString: true,
  706. callback: (action) => {
  707. if (action === 'confirm') {
  708. firstItemHttp(info)
  709. }
  710. }
  711. })
  712. }
  713. //首件请求
  714. const firstItemHttp = async (info) => {
  715. const { error, code } = await wbsApi.wbsTreeFirstSave({
  716. primaryKeyId: info['primaryKeyId'],
  717. saveOrDeleted: !!info['isFirst']?1:0,
  718. })
  719. //处理数据
  720. if (!error && code === 200) {
  721. window?.$message?.success('操作成功')
  722. window?.location?.reload() //刷新页面
  723. }
  724. }
  725. //编辑节点
  726. const editNodeModal = ref(false)
  727. //获取节点类型
  728. const nodeTypeData = ref([])
  729. const getDictionaryApi = async () => {
  730. const { data } = await getDictionary({
  731. code: 'wbs_node_type'
  732. })
  733. //处理数据
  734. let newArr = []
  735. const newData = getArrValue(data)
  736. for (let i = 0; i < newData.length; i++) {
  737. newArr.push({
  738. label: newData[i]['dictValue'],
  739. value: Number(newData[i]['dictKey']),
  740. })
  741. }
  742. nodeTypeData.value = newArr
  743. }
  744. const formEditNodeRef = ref(null)
  745. const formEditNodeModel = ref({})
  746. const formEditNodeRules = {
  747. title: {
  748. required: true,
  749. trigger: 'blur',
  750. message: "请输入节点名称"
  751. },
  752. }
  753. const editNodeLoading = ref(false)
  754. //保存编辑节点数据
  755. const editNodeClick = async () => {
  756. const validate = await formValidate(formEditNodeRef.value)
  757. if (validate) {
  758. //发起请求
  759. editNodeLoading.value = true
  760. const { primaryKeyId, title, partitionCode } = formEditNodeModel.value
  761. const { error, code } = await wbsApi.wbsTreeUpdateNode({
  762. nodeName: title || '',
  763. pKeyId: primaryKeyId || '',
  764. partitionCode: partitionCode || ''
  765. })
  766. //处理数据
  767. editNodeLoading.value = false
  768. if (!error && code === 200) {
  769. window?.$message?.success('修改成功')
  770. nodeDataInfo.value['title'] = title || ''
  771. nodeDataInfo.value['partitionCode'] = partitionCode || ''
  772. editNodeModal.value = false
  773. window?.location?.reload() //刷新页面
  774. }
  775. }
  776. }
  777. //复制节点
  778. const copyNodeModal = ref(false)
  779. //复制节点类型tab数据和相关处理
  780. const copyNodeTabKey = ref('1')
  781. const copyNodeTab = ref([
  782. {key:'1', name: '单份复制'},
  783. {key:'2', name: '多份复制'},
  784. {key:'3', name: '复制数据'}
  785. ]);
  786. const copyNodeTabChange = (key) => {
  787. if (key !== copyNodeTabKey.value) {
  788. copyNodeTabKey.value = key;
  789. copyNodeTable.value = []
  790. copyNodeLoading.value = false
  791. }
  792. }
  793. //复制节点变量
  794. const copyNodeLoading = ref(false)
  795. const formCopyNodeModel = ref({})
  796. const copyNodeTable = ref([])
  797. //复制树被点击
  798. const copyNodeElTreeClick = ({data}) => {
  799. const TabKey = copyNodeTabKey.value;
  800. const {title, type} = formCopyNodeModel.value;
  801. if (TabKey === '2') {
  802. //1 单位工程,2 分部工程,3 子分部工程,4 分项工程, 5 子分项工程,6 工序
  803. //工序节点不能复制到工序节点下面
  804. // if (type === 6 && (data['type'] === 4 || data['type'] === 5 || data['type'] == 6)) {
  805. // setCopyNodeTable(data, title)
  806. // }
  807. if (type === 6 && (data['type'] === 4 || data['type'] === 5 || data['type'] !== 6)) {
  808. setCopyNodeTable(data, title)
  809. }
  810. if (type === 5 && data['type'] === 4) {
  811. setCopyNodeTable(data, title)
  812. }
  813. if (type === 4 && (data['type'] === 2 || data['type'] === 3)) {
  814. setCopyNodeTable(data, title)
  815. }
  816. if (type === 3 && data['type'] === 2) {
  817. setCopyNodeTable(data, title)
  818. }
  819. if (type === 2 && data['type'] === 1) {
  820. setCopyNodeTable(data, title)
  821. }
  822. if (type === 1 && data['type'] === 1) {
  823. setCopyNodeTable(data, title)
  824. }
  825. } else if (TabKey === '3') {
  826. if (data['notExsitChild']) {
  827. setCopyNodeTable(data, data?.title)
  828. }
  829. }
  830. }
  831. const setCopyNodeTable = (data, title) => {
  832. copyNodeTable.value.push({
  833. title: data?.title || '',
  834. nodeName: title || '',
  835. primaryKeyId: data?.primaryKeyId || ''
  836. })
  837. }
  838. //节点表单
  839. const formCopyNodeModelRef = ref(null)
  840. const formCopyNodeModelRules = {
  841. title: {
  842. required: true,
  843. trigger: "blur",
  844. message: "请输入节点名称"
  845. }
  846. }
  847. //表格节点表单
  848. const copyNodeTableRef = ref(null)
  849. const copyNodeTableRules = {
  850. nodeName: {
  851. required: true,
  852. trigger: "blur",
  853. message: "请输入节点名称"
  854. }
  855. }
  856. //删除选中的节点
  857. const copyNodeTableDel = (index) => {
  858. copyNodeTable.value.splice(index,1)
  859. }
  860. //复制节点
  861. const copyNodeClick = async () => {
  862. const type = copyNodeTabKey.value
  863. const form = formCopyNodeModel.value
  864. const table = copyNodeTable.value
  865. //效验数据
  866. if (type === '1') {
  867. const validate = await formValidate(formCopyNodeModelRef.value)
  868. if (validate) await copyContractTreeNode(type, form,[])
  869. } else if (type === '2') {
  870. if (table.length > 0) {
  871. const validate = await formValidate(copyNodeTableRef.value)
  872. if (validate) await copyContractTreeNode(type, form,table)
  873. } else {
  874. window?.$message?.warning('请先在左侧选择要复制到的节点')
  875. }
  876. } else if (type === '3') {
  877. if (table.length > 0) {
  878. await copyContractNodeSubmitBusinessData(form,table)
  879. } else {
  880. window?.$message?.warning('请先在左侧选择要复制的节点')
  881. }
  882. }
  883. }
  884. //单个复制、多份复制请求
  885. const copyContractTreeNode = async (type, form,table) => {
  886. copyNodeLoading.value = true
  887. const {error, code} = await wbsApi.copyContractTreeNode({
  888. copyType: type,
  889. needCopyNodeName: form?.title || '',
  890. needCopyPrimaryKeyId: form?.primaryKeyId || '',
  891. parentPrimaryKeyId: form?.parent?.primaryKeyId || '',
  892. copyBatchToPaths: table
  893. })
  894. //判断状态
  895. if (!error && code === 200) {
  896. window?.$message?.success('复制成功')
  897. copyNodeLoading.value = false
  898. copyNodeModal.value = false
  899. window?.location?.reload() //刷新页面
  900. }
  901. }
  902. //复制数据
  903. const copyContractNodeSubmitBusinessData = async (form,table) => {
  904. copyNodeLoading.value = true
  905. const {error, code} = await wbsApi.copyContractNodeSubmitBusinessData({
  906. needCopyPrimaryKeyId: form?.primaryKeyId || '',
  907. copyBatchToPaths: table
  908. })
  909. //判断状态
  910. if (!error && code === 200) {
  911. window?.$message?.success('复制成功')
  912. copyNodeLoading.value = false
  913. copyNodeModal.value = false
  914. window?.location?.reload() //刷新页面
  915. }
  916. }
  917. //新增节点
  918. const addNodeModal = ref(false)
  919. const addTreeNodeId = ref('')
  920. const addTreeNodeOldId = ref('')
  921. const addTreeNodeType = ref('1')
  922. //选中的节点
  923. const allSelectedList = ref([])
  924. const halfSelectedList = ref([])
  925. const addTreeNodeCheckChange = (nodes) => {
  926. let NodesArr = [], halfArr = []
  927. //全选数据
  928. const keys = nodes.checkedNodes || []
  929. for (let i = 0; i < keys.length; i++) {
  930. NodesArr.push({
  931. nodeName: keys[i].title,
  932. primaryKeyId: keys[i].primaryKeyId
  933. })
  934. }
  935. allSelectedList.value = NodesArr
  936. //半选数据
  937. const halfNodes = nodes.halfCheckedNodes || []
  938. for (let i = 0; i < halfNodes.length; i++) {
  939. halfArr.push({
  940. nodeName: halfNodes[i].title,
  941. primaryKeyId: halfNodes[i].primaryKeyId
  942. })
  943. }
  944. halfSelectedList.value = halfArr
  945. }
  946. //新增节点
  947. const addNodeLoading = ref(false)
  948. const addNodeClick = async () => {
  949. const keys = allSelectedList.value || []
  950. if (keys.length <= 0) {
  951. window?.$message?.warning('请先选择节点')
  952. } else {
  953. //发起请求
  954. addNodeLoading.value = true
  955. const primaryKeyId = nodeDataInfo.value?.primaryKeyId || ''
  956. const {error, code} = await wbsApi.saveContractTreeNode({
  957. projectId: projectId.value,
  958. contractId: contractId.value,
  959. saveType: addTreeNodeType.value,
  960. allSelectedList: allSelectedList.value,
  961. halfSelectedList: halfSelectedList.value,
  962. currentNodePrimaryKeyId: primaryKeyId
  963. })
  964. //判断状态
  965. addNodeLoading.value = false
  966. if (!error && code === 200) {
  967. window?.$message?.success('新增成功')
  968. addNodeModal.value = false
  969. window?.location?.reload() //刷新页面
  970. }
  971. }
  972. }
  973. //删除节点
  974. const delModalClick = () => {
  975. window?.$messageBox?.alert('请谨慎考虑后,确认是否需要删除?', '删除节点', {
  976. showCancelButton: true,
  977. confirmButtonText: '确认删除',
  978. cancelButtonText: '取消',
  979. callback: (action) => {
  980. if (action === 'confirm') {
  981. removeContractTreeNode()
  982. }
  983. }
  984. })
  985. }
  986. const removeContractTreeNode = async () => {
  987. const {error, code} = await wbsApi.removeContractTreeNode({
  988. ids: nodeDataInfo.value?.primaryKeyId || ''
  989. })
  990. if (!error && code === 200) {
  991. window?.$message?.success('删除成功')
  992. window?.location?.reload() //刷新页面
  993. }
  994. }
  995. //调整排序
  996. const sortNodeModal = ref(false)
  997. const sortNodeLoading = ref(false)
  998. const sortNodeData = ref([])
  999. const sortNodeDrag = ref(false)
  1000. //向下
  1001. const downSortClick = (index) => {
  1002. const indexs = index + 1
  1003. const data = sortNodeData.value || []
  1004. if(indexs !== data.length) {
  1005. const tmp = data.splice(indexs,1);
  1006. sortNodeData.value.splice(index,0,tmp[0]);
  1007. } else {
  1008. window?.$message?.warning('已经处于置底,无法下移')
  1009. }
  1010. }
  1011. //向上
  1012. const upSortClick = (index) => {
  1013. const data = sortNodeData.value || []
  1014. if(index !== 0) {
  1015. const tmp = data.splice(index - 1,1);
  1016. sortNodeData.value.splice(index,0,tmp[0]);
  1017. } else {
  1018. window?.$message?.warning('已经处于置顶,无法上移')
  1019. }
  1020. }
  1021. //确认排序
  1022. const sortNodeClick = async () => {
  1023. const sortList = [];
  1024. const nodes = sortNodeData.value || []
  1025. nodes.forEach(item => {
  1026. sortList.push(item?.id)
  1027. })
  1028. //发起请求
  1029. sortNodeLoading.value = true
  1030. const { error, code } = await wbsApi.diySortTreeNode({sortList})
  1031. sortNodeLoading.value = false
  1032. //判断状态
  1033. if (!error && code === 200) {
  1034. window?.$message?.success('保存成功')
  1035. sortNodeModal.value = false
  1036. window?.location?.reload() //刷新页面
  1037. }
  1038. }
  1039. //查看图纸
  1040. const drawingsShow = ref(false);
  1041. const viewsDrawings = () => {
  1042. const {primaryKeyId, fileUrl} = nodeDataInfo.value
  1043. if (!primaryKeyId) {
  1044. window?.$message?.warning('请先选择树节点')
  1045. } else if (!fileUrl) {
  1046. window?.$message?.warning('该节点暂未上传图纸')
  1047. } else {
  1048. drawingsShow.value = true
  1049. }
  1050. }
  1051. const drawingsClose = (res) => {
  1052. drawingsShow.value = res
  1053. }
  1054. //设置滚动条位置
  1055. const ListItemScrollRef = ref(null)
  1056. const ListItemOffsetTop = (offsetTop) => {
  1057. if (offsetTop > 0) {
  1058. setTimeout(() => {
  1059. ListItemScrollRef.value?.setScrollTop(offsetTop)
  1060. }, 350)
  1061. } else {
  1062. ListItemScrollRef.value?.setScrollTop(offsetTop)
  1063. }
  1064. }
  1065. //获取数据列表
  1066. const ListItemDatas = ref([]);
  1067. const ListItemLoading = ref(false);
  1068. const searchNodeAllTable = async () => {
  1069. ListItemDatas.value = []
  1070. const info = nodeDataInfo.value;
  1071. ListItemLoading.value = true
  1072. const {error, code, data} = await wbsApi.searchNodeAllTable({
  1073. projectId: projectId.value,
  1074. contractId: contractId.value,
  1075. primaryKeyId: info['primaryKeyId'],
  1076. type: authBtnTabKey.value
  1077. })
  1078. //处理数据
  1079. ListItemLoading.value = false
  1080. if (!error && code === 200) {
  1081. ListItemDatas.value = getArrValue(data)
  1082. } else {
  1083. ListItemDatas.value = []
  1084. }
  1085. }
  1086. //查询状态
  1087. const NodeStatus = ref('1')
  1088. const queryNodeStatus = async () => {
  1089. const info = nodeDataInfo.value;
  1090. const {error, code, data} = await wbsApi.queryNodeStatus({
  1091. primaryKeyId: info['contractIdRelation'] ? info['id'] : info['primaryKeyId'],
  1092. classify: authBtnTabKey.value
  1093. })
  1094. //1 未填报,2待上报,3已上报
  1095. if (!error && code === 200) {
  1096. NodeStatus.value = data ?? '1'
  1097. } else {
  1098. NodeStatus.value = '1'
  1099. }
  1100. }
  1101. //批量上报
  1102. const reportIds = ref('')
  1103. const reportTaskName = ref('')
  1104. const reportAddition = ref({})
  1105. const showReportModal = ref(false)
  1106. const reportLoading = ref(false)
  1107. const reportTypeData = ref([])
  1108. const reportModalClick = async () => {
  1109. const info = nodeDataInfo.value;
  1110. const rows = ListItemDatas.value;
  1111. if (rows.length > 0) {
  1112. reportLoading.value = true
  1113. const taskCheck = await eVisaTaskCheckApi({
  1114. projectId: projectId.value,
  1115. contractId: contractId.value
  1116. })
  1117. //处理数据
  1118. let newArr = [];
  1119. for (let i = 0; i < rows.length; i++) {
  1120. newArr.push(rows[i]['isTypePrivatePid'])
  1121. }
  1122. reportTypeData.value = newArr
  1123. reportLoading.value = false
  1124. if (taskCheck) {
  1125. //初始弹出弹窗,防呆
  1126. reportIds.value = info['primaryKeyId']
  1127. reportAddition.value = {
  1128. classify: authBtnTabKey.value,
  1129. contractIdRelation: info['contractIdRelation'],
  1130. }
  1131. showReportModal.value = true
  1132. //请求文件题名
  1133. const {data} = await wbsApi.queryDocumentTitle({
  1134. primaryKeyId: info['primaryKeyId'],
  1135. classify: authBtnTabKey.value
  1136. })
  1137. reportTaskName.value = isString(data)? data : ''
  1138. }
  1139. } else {
  1140. window.$message?.warning('暂无相关数据')
  1141. }
  1142. }
  1143. //上报完成
  1144. const showReportFinish = () => {
  1145. showReportModal.value = false
  1146. getTableDataAll()
  1147. window?.location?.reload() //刷新页面
  1148. }
  1149. //表单变量
  1150. const ListItemRef = ref(null)
  1151. const ListItemsRef = ref(null)
  1152. //保存
  1153. const tableFormSaveLoading = ref(false)
  1154. const tableFormSaveClick = async () => {
  1155. //获取数据
  1156. let FormData = [], FormRegExpJson = {};
  1157. if (isDrawer.value) {
  1158. FormData = ListItemsRef.value?.getFormData()
  1159. FormRegExpJson = ListItemsRef.value?.getFormRegExpJson()
  1160. } else {
  1161. FormData = ListItemRef.value?.getFormData()
  1162. FormRegExpJson = ListItemRef.value?.getFormRegExpJson()
  1163. }
  1164. //效验数据
  1165. if (getObjNullValue(FormRegExpJson)) {
  1166. setFormRegExpJson(FormRegExpJson)
  1167. } else if (FormData.length > 0) {
  1168. tableFormSaveLoading.value = true
  1169. const {error, code} = await wbsApi.saveExcelBussData({
  1170. dataInfo: {orderList: FormData}
  1171. })
  1172. tableFormSaveLoading.value = false
  1173. if (!error && code === 200) {
  1174. window?.$message?.success('保存成功')
  1175. bussPdfsClick()
  1176. getTableDataAll()
  1177. }
  1178. } else {
  1179. //http://testcandao.hcxxy.com/bug-view-819.html
  1180. bussPdfsClick()
  1181. }
  1182. }
  1183. //效验数据
  1184. const setFormRegExpJson = (FormRegExpJson) => {
  1185. let nodeName = '', itemId = '';
  1186. Object.keys(FormRegExpJson).forEach(key => {
  1187. const name = FormRegExpJson[key]?.nodeName ?? ''
  1188. if (name) {
  1189. if (nodeName) {
  1190. nodeName += ',' + name
  1191. } else {
  1192. nodeName = name
  1193. itemId = FormRegExpJson[key]?.itemId
  1194. }
  1195. }
  1196. })
  1197. //const activeKey = ListItemRef.value?.getActiveKey()
  1198. //弹出提示
  1199. const val = '<div style="font-size: 16px;">请先完善 <span style="color:#1ECC95;">' + nodeName + '</span> 的数据内容</div>'
  1200. window?.$messageBox?.alert(val, '表单完善提醒', {
  1201. confirmButtonText: '确定',
  1202. dangerouslyUseHTMLString: true,
  1203. callback: (action) => {
  1204. if (action === 'confirm') {
  1205. ListItemRef.value?.setActiveKey(itemId)
  1206. ListItemOffsetTop(0)
  1207. setTimeout(() => {
  1208. const offsetTop = document.getElementById(itemId)?.offsetTop
  1209. ListItemOffsetTop(offsetTop)
  1210. }, 350)
  1211. }
  1212. }
  1213. })
  1214. }
  1215. //多表预览
  1216. const bussPdfsLoading = ref(false)
  1217. const bussPdfsClick = async () => {
  1218. const info = nodeDataInfo.value;
  1219. bussPdfsLoading.value = true
  1220. const {error, code, data} = await wbsApi.getBussPdfs({
  1221. nodeId: info?.primaryKeyId || '',
  1222. classify: authBtnTabKey.value,
  1223. projectId: projectId.value,
  1224. contractId: contractId.value
  1225. })
  1226. tableFormSaveLoading.value = false
  1227. bussPdfsLoading.value = false
  1228. if (!error && code === 200) {
  1229. window.open(data,'_blank')
  1230. } else {
  1231. window.$message?.warning('获取PDF失败')
  1232. }
  1233. }
  1234. //撤回上报流程
  1235. const abolishOneClick = () => {
  1236. window?.$messageBox?.alert('请谨慎考虑后,是否确定撤回?', '撤回上报', {
  1237. showCancelButton: true,
  1238. confirmButtonText: '确定撤回',
  1239. cancelButtonText: '取消',
  1240. callback: (action) => {
  1241. if (action === 'confirm') {
  1242. abolishOneSave()
  1243. }
  1244. }
  1245. })
  1246. }
  1247. //撤回请求
  1248. const abolishOneSave = async () => {
  1249. const info = nodeDataInfo.value;
  1250. const {error, code} = await wbsApi.abolishOne({
  1251. primaryKeyId: info?.primaryKeyId || '',
  1252. classify: authBtnTabKey.value
  1253. })
  1254. if (!error && code === 200) {
  1255. window.$message?.success('撤回成功')
  1256. getTableDataAll()
  1257. window?.location?.reload() //刷新页面
  1258. }
  1259. }
  1260. //划分变更
  1261. const divisionClick = () => {
  1262. router.push({
  1263. path: '/data-fill/division'
  1264. })
  1265. }
  1266. //左右拖动,改变树形结构宽度
  1267. const leftWidth = ref(382);
  1268. const onmousedown = () => {
  1269. const leftNum = isCollapse.value ? 142 : 272
  1270. document.onmousemove = (ve) => {
  1271. let diffVal = ve.clientX - leftNum;
  1272. if(diffVal >= 310 && diffVal <= 900) {
  1273. leftWidth.value = diffVal;
  1274. }
  1275. }
  1276. document.onmouseup = () => {
  1277. document.onmousemove = null;
  1278. document.onmouseup = null;
  1279. }
  1280. }
  1281. </script>
  1282. <style lang="scss" scoped>
  1283. @import "../../styles/data-fill/wbs.scss";
  1284. .hc-add-node-modal-foot-box {
  1285. position: relative;
  1286. display: flex;
  1287. align-items: center;
  1288. .left-box {
  1289. position: relative;
  1290. flex: 1;
  1291. display: flex;
  1292. align-items: center;
  1293. }
  1294. .right-box {
  1295. position: relative;
  1296. }
  1297. }
  1298. html.theme-dark {
  1299. .bg-svg-xml {
  1300. background-color: initial;
  1301. background-image: initial;
  1302. }
  1303. .hc-layout-box .hc-layout-content-box .hc-card-max-h-box.node-tree .hc-tree-foot-tip-box {
  1304. border-top: 1px solid #303030;
  1305. }
  1306. }
  1307. </style>
  1308. <style lang="scss">
  1309. .data-fill-wbs-content {
  1310. position: relative;
  1311. height: 100%;
  1312. .n-drawer-container {
  1313. margin: -20px -24px;
  1314. }
  1315. .n-drawer.n-drawer--top-placement {
  1316. height: auto !important;
  1317. background-color: initial;
  1318. pointer-events: none;
  1319. bottom: 0;
  1320. }
  1321. .drawer-data-fill-content-box {
  1322. position: relative;
  1323. height: 100%;
  1324. padding: 24px;
  1325. .n-card {
  1326. pointer-events: auto;
  1327. height: 100%;
  1328. overflow: auto;
  1329. }
  1330. .data-fill-content {
  1331. position: relative;
  1332. height: 100%;
  1333. overflow-y: auto;
  1334. scroll-behavior: smooth;
  1335. .data-fill-list-box .data-fill-list-item-content {
  1336. height: calc(100vh - 470px);
  1337. .data-fill-table-form-box {
  1338. height: 100%;
  1339. }
  1340. }
  1341. }
  1342. .data-fill-foot {
  1343. position: relative;
  1344. text-align: center;
  1345. }
  1346. }
  1347. }
  1348. .n-card.hc-card-overflow-box .n-card__content {
  1349. padding: 24px;
  1350. }
  1351. .n-card.hc-custom-card > .n-card-header {
  1352. padding: 15px 24px;
  1353. }
  1354. .n-card.hc-custom-card.copy {
  1355. width: 1200px;
  1356. max-height: 90vh;
  1357. overflow: auto;
  1358. .n-card-header .n-card-header__close {
  1359. display: none;
  1360. }
  1361. &.one {
  1362. width: 600px;
  1363. }
  1364. &.many {
  1365. width: 1200px;
  1366. }
  1367. }
  1368. .img-preview-box {
  1369. position: relative;
  1370. height: 100%;
  1371. width: 100%;
  1372. }
  1373. </style>