division.vue 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412
  1. <template>
  2. <div class="hc-page-layout-box">
  3. <div :style="'width:' + leftWidth + 'px;'" class="hc-layout-left-box">
  4. <div class="hc-project-box">
  5. <div class="hc-project-icon-box">
  6. <HcIcon name="stack"/>
  7. </div>
  8. <div class="ml-2 project-name-box">
  9. <span class="text-xl text-cut project-alias">{{ projectInfo['projectAlias'] }}</span>
  10. <div class="text-xs text-cut project-name">{{ projectInfo['name'] }}</div>
  11. </div>
  12. </div>
  13. <div v-loading="treeLoading" class="hc-tree-box" element-loading-text="加载中...">
  14. <el-scrollbar>
  15. <WbsTree :autoExpandKeys="treeAutoExpandKeys" :classifyType="classifyType" :contractId="contractId"
  16. :menus="ElTreeMenu"
  17. :projectId="projectId"
  18. :submitCounts="true" isColor ui="page-division-tree" @menuTap="ElTreeMenuClick"
  19. @nodeLoading="treeNodeLoading" @nodeTap="wbsElTreeClick"/>
  20. </el-scrollbar>
  21. </div>
  22. <!--左右拖动-->
  23. <div class="horizontal-drag-line" @mousedown="onmousedown"/>
  24. </div>
  25. <div class="hc-page-content-box hc-division-page">
  26. <div class="basic-info">
  27. <HcCard title="当前节点基础信息">
  28. <template #extra>
  29. <el-checkbox v-model="treeItemInfo.isConcealedWorksNode" :false-label="0"
  30. :true-label="1" label="标记为隐蔽工程节点" size="large" @change="concealedChange"/>
  31. </template>
  32. <HcTable :column="tableBasicColumn" :datas="tableBasicData" :isIndex="false" border>
  33. <template #type="{row}">{{ getRowType(row['type']) }}</template>
  34. <template #majorDataType="{row}">{{ getRowMajorType(row['majorDataType']) }}</template>
  35. </HcTable>
  36. </HcCard>
  37. </div>
  38. <div class="project-info">
  39. <HcCard title="当前节点工程用表信息">
  40. <template #extra>
  41. <el-button hc-btn type="primary" @click="addingFormClick">
  42. <HcIcon name="add"/>
  43. <span>引用元素表</span>
  44. </el-button>
  45. </template>
  46. <HcTable :column="tableProjectColumn" :datas="tableProjectData" :isIndex="false" border>
  47. <template #tableType="{row}">{{ getRowTableType(row['tableType']) }}</template>
  48. <template #tableOwner="{row}">{{ getRowTableOwnerType(row['tableOwner']) }}</template>
  49. <template #action="{row}">
  50. <HcTooltip keys="wbs_views_delexcel">
  51. <el-button plain size="small" type="primary" @click="deltableexcel(row)">
  52. <HcIcon name="delete-bin"/>
  53. <span>删除</span>
  54. </el-button>
  55. </HcTooltip>
  56. </template>
  57. </HcTable>
  58. </HcCard>
  59. </div>
  60. <div class="footer-box">
  61. <el-button hc-btn @click="downloadXlsx">
  62. <HcIcon name="download-2"/>
  63. <span>下载导入划分模板</span>
  64. </el-button>
  65. <el-button :disabled="!treePrimaryKeyId" hc-btn type="primary" @click="toImportTempClick">
  66. <HcIcon name="folder-upload"/>
  67. <span>导入划分模板</span>
  68. </el-button>
  69. <el-button hc-btn @click="toBackClick">
  70. <HcIcon name="arrow-go-back"/>
  71. <span>进入资料填报</span>
  72. </el-button>
  73. </div>
  74. </div>
  75. <!--编辑节点-->
  76. <HcDialog :loading="editNodeLoading" :show="editNodeModal" title="编辑节点"
  77. widths="600px" @close="editNodeModal = false" @save="editNodeClick">
  78. <el-form ref="formEditNodeRef" :model="formEditNodeModel" :rules="formEditNodeRules" label-width="auto"
  79. size="large">
  80. <el-form-item label="节点名称" prop="title">
  81. <el-input v-model="formEditNodeModel.title" placeholder="请输入节点名称"/>
  82. </el-form-item>
  83. <el-form-item label="上级节点">
  84. <el-input v-model="formEditNodeModel.parent.title" disabled/>
  85. </el-form-item>
  86. <el-form-item label="节点类型">
  87. <el-select v-model="formEditNodeModel.type" block disabled>
  88. <el-option v-for="item in nodeTypeData" :label="item['label']" :value="item['value']"/>
  89. </el-select>
  90. </el-form-item>
  91. <el-form-item label="划分编号">
  92. <el-input v-model="formEditNodeModel.partitionCode" placeholder="请输入划分编号"/>
  93. </el-form-item>
  94. </el-form>
  95. </HcDialog>
  96. <!--复制节点-->
  97. <HcDialog :loading="copyNodeLoading" :show="copyNodeModal" :widths="copyNodeTabKey === '1'?'600px':'1200px'"
  98. loading-text="复制节点中,请耐心等待..." title="复制节点" @close="copyNodeModal = false">
  99. <el-form v-if="copyNodeTabKey !== '3'" ref="formCopyNodeModelRef" :model="formCopyNodeModel"
  100. :rules="formCopyNodeModelRules" label-width="auto" size="large">
  101. <el-form-item v-if="copyNodeTabKey === '1'" label="节点名称" prop="title" style="margin-bottom: 0;">
  102. <el-input v-model="formCopyNodeModel.title" placeholder="请输入节点名称"/>
  103. </el-form-item>
  104. <el-form-item v-if="copyNodeTabKey === '1'" label="划分编号" prop="partitionCode"
  105. style="margin-top: 10px;">
  106. <el-input v-model="formCopyNodeModel.partitionCode" placeholder="请输入划分编号"/>
  107. </el-form-item>
  108. </el-form>
  109. <el-form v-if="copyNodeTabKey === '3'" ref="formCopyNodeModelRef" :model="formCopyNodeModel"
  110. :rules="formCopyNodeModelRules" label-width="auto" size="large">
  111. <el-form-item label="所属方" prop="classify" style="margin-bottom: 0;">
  112. <!-- <el-input v-model="formCopyNodeModel.classify" placeholder="请输入节点名称"/> -->
  113. <el-checkbox-group v-model="classifyList">
  114. <el-checkbox label="施工"/>
  115. <el-checkbox label="监理"/>
  116. </el-checkbox-group>
  117. </el-form-item>
  118. </el-form>
  119. <div v-if="copyNodeTabKey !== '1'" class="copy-node-many-box">
  120. <div class="copy-node-many-tree">
  121. <el-scrollbar>
  122. <WbsTree :autoExpandKeys="TreeAutoExpandKeys" :contractId="contractId" :isAutoClick="false"
  123. :isAutoKeys="false" :projectId="projectId" idPrefix="tree-node-copy-"
  124. @nodeTap="copyNodeElTreeClick"/>
  125. </el-scrollbar>
  126. </div>
  127. <div class="copy-node-many-table">
  128. <el-scrollbar>
  129. <el-table :data="copyNodeTable" border stripe>
  130. <el-table-column label="复制到的位置" prop="title"/>
  131. <el-table-column v-if="copyNodeTabKey === '2'" label="节点名称" prop="nodeName">
  132. <template #default="{row}">
  133. <el-form ref="copyNodeTableRef" :model="row" :rules="copyNodeTableRules"
  134. label-width="0" size="large">
  135. <el-form-item prop="nodeName" style="margin-bottom: 0;">
  136. <el-input v-model="row.nodeName" placeholder="请输入节点名称"/>
  137. </el-form-item>
  138. </el-form>
  139. </template>
  140. </el-table-column>
  141. <el-table-column v-if="copyNodeTabKey === '2'" label="划分编号" prop="nodeName">
  142. <template #default="{row}">
  143. <el-form ref="copyNodeTableRef" :model="row" :rules="copyNodeTableRules"
  144. label-width="0" size="large">
  145. <el-form-item prop="partitionCode" style="margin-bottom: 0;">
  146. <el-input v-model="row.partitionCode" placeholder="请输入划分编号"/>
  147. </el-form-item>
  148. </el-form>
  149. </template>
  150. </el-table-column>
  151. <el-table-column align="center" label="操作" prop="action" width="120">
  152. <template #default="{_,$index}">
  153. <el-button plain type="danger" @click="copyNodeTableDel($index)">删除</el-button>
  154. </template>
  155. </el-table-column>
  156. </el-table>
  157. </el-scrollbar>
  158. </div>
  159. </div>
  160. <template #footer>
  161. <div class="lr-dialog-footer">
  162. <div class="left">
  163. <template v-for="item in copyNodeTab">
  164. <el-button v-if="item?.key === copyNodeTabKey" plain size="large" type="primary"
  165. @click="copyNodeTabChange(item?.key)">{{ item.name }}
  166. </el-button>
  167. <el-button v-else bg size="large" text @click="copyNodeTabChange(item?.key)">
  168. {{ item.name }}
  169. </el-button>
  170. </template>
  171. </div>
  172. <div class="right">
  173. <el-button size="large" @click="copyNodeModal = false">取消</el-button>
  174. <el-button :loading="copyNodeLoading" hc-btn type="primary" @click="copyNodeClick">提交
  175. </el-button>
  176. </div>
  177. </div>
  178. </template>
  179. </HcDialog>
  180. <!--新增子节点-->
  181. <HcDialog :loading="addNodeLoading" :show="addNodeModal" loading-text="新增节点中,请耐心等待..."
  182. title="新增子节点" widths="720px" @close="addNodeModal = false">
  183. <el-alert :closable="false" title="双击节点,可编辑节点名称,编辑完成后,请按回车或输入框消失后,再点提交"
  184. type="warning"/>
  185. <HcTreeNode v-if="addTreeNodeType === '1'" :nodeId="addTreeNodeId" :oldId="addTreeNodeOldId"
  186. :projectId="projectId" @check-change="addTreeNodeCheckChange"/>
  187. <HcTreeNode v-if="addTreeNodeType === '2'" :nodeId="addTreeNodeId" :oldId="addTreeNodeOldId"
  188. :projectId="projectId"
  189. strictly @check-change="addTreeNodeCheckChange"/>
  190. <template #footer>
  191. <div class="lr-dialog-footer">
  192. <div class="left flex items-center">
  193. <div class="mr-4">选中方式:</div>
  194. <el-radio-group v-model="addTreeNodeType">
  195. <el-radio label="1">当前及子节点</el-radio>
  196. <el-radio class="ml-4" label="2">仅当前节点</el-radio>
  197. </el-radio-group>
  198. </div>
  199. <div class="right">
  200. <el-button size="large" @click="addNodeModal = false">取消</el-button>
  201. <el-button :loading="addNodeLoading" hc-btn type="primary" @click="addNodeClick">提交
  202. </el-button>
  203. </div>
  204. </div>
  205. </template>
  206. </HcDialog>
  207. <!--调整排序-->
  208. <HcDialog :loading="sortNodeLoading" :show="sortNodeModal" title="调整排序" widths="700px"
  209. @close="sortNodeModal = false" @save="sortNodeClick">
  210. <el-alert :closable="false" title="可拖动排序,也可在后面点击图标,切换排序" type="warning"/>
  211. <div class="sort-node-body-box list-group header">
  212. <div class="list-group-item">
  213. <div class="index-box">序号</div>
  214. <div class="title-box">节点名称</div>
  215. <div class="icon-box">排序</div>
  216. </div>
  217. </div>
  218. <Draggable :list="sortNodeData" class="sort-node-body-box list-group" ghost-class="ghost" item-key="id"
  219. @end="sortNodeDrag = false" @start="sortNodeDrag = true">
  220. <template #item="{element, index}">
  221. <div class="list-group-item">
  222. <div class="index-box">{{ index + 1 }}</div>
  223. <div class="title-box">{{ element.title }}</div>
  224. <div class="icon-box">
  225. <span class="icon" @click="downSortClick(index)">
  226. <HcIcon name="arrow-down" ui="text-lg"/>
  227. </span>
  228. <span class="icon" @click="upSortClick(index)">
  229. <HcIcon name="arrow-up" ui="text-lg"/>
  230. </span>
  231. </div>
  232. </div>
  233. </template>
  234. </Draggable>
  235. </HcDialog>
  236. <!--导入划分模板-->
  237. <HcDialog :show="importTempModal" title="导入划分模板" ui="hc-modal-table" widths="84%"
  238. @close="importTempModal = false">
  239. <div class="hc-import-temp-box">
  240. <!--div class="hc-choose-type-box">
  241. <div class="text-title text-orange">请选择需要导入的工程类别:</div>
  242. <div class="hc-type-box">
  243. <el-radio-group v-model="importRadio" size="large">
  244. <el-radio v-for="item in importRadioData" :label="item.key">{{item.name}}</el-radio>
  245. </el-radio-group>
  246. </div>
  247. </div-->
  248. <div v-loading="uploadLoading" class="hc-import-node-tree-box" element-loading-text="Loading...">
  249. <div class="import-node-tree-box">
  250. <div class="hc-tree-title-box">导入并识别成功</div>
  251. <div class="hc-tree-bar-box">
  252. <el-scrollbar>
  253. <HcTreeData :datas="matchedData"/>
  254. </el-scrollbar>
  255. </div>
  256. </div>
  257. <div class="import-node-tree-box">
  258. <div class="hc-tree-title-box">未被系统识别:手动关联</div>
  259. <div class="hc-tree-bar-box">
  260. <el-scrollbar>
  261. <HcTreeData1 :datas="unmatchedData" @relationTap="unmatchedTreeTap"/>
  262. </el-scrollbar>
  263. </div>
  264. </div>
  265. </div>
  266. </div>
  267. <template #footer>
  268. <div class="lr-dialog-footer">
  269. <div class="left">
  270. <HcUpload ref="uploadRef" :contractId="contractId" :isSplicingNumber="isSplicingNumber"
  271. :primaryKeyId="treePrimaryKeyId" :type="importRadio"
  272. @change="uploadChange" @finished="uploadFinished" @progress="uploadprogress"/>
  273. </div>
  274. <div class="right flex">
  275. <div class="mr-6">
  276. <span class="text-grey">是否拼接划分编号:</span>
  277. <el-switch v-model="isSplicingNumber" :active-value="1" :inactive-value="0" active-text="是"
  278. inactive-text="否" inline-prompt size="large"/>
  279. </div>
  280. <el-button size="large" @click="importTempModalClose">
  281. <HcIcon name="close"/>
  282. <span>取消</span>
  283. </el-button>
  284. <el-button :disabled="uploadLoading" :loading="uploadLoading" hc-btn type="primary"
  285. @click="importTempFolder">
  286. <HcIcon name="folder-upload"/>
  287. <span>导入模板</span>
  288. </el-button>
  289. </div>
  290. </div>
  291. </template>
  292. </HcDialog>
  293. <!--替换并关联节点-->
  294. <HcDialog :loading="relationLoading" :show="relationModal" saveText="确认关联" title="替换并关联节点"
  295. ui="hc-modal-table"
  296. widths="47rem" @close="relationModal = false" @save="relationSaveClick">
  297. <el-scrollbar>
  298. <DivisionTree :datas="unmatchedTreeData" @nodeTap="divisionTreeClick"/>
  299. </el-scrollbar>
  300. </HcDialog>
  301. <!--添加独立表单-->
  302. <HcDialog :loading="addingFormLoading" :padding="false" :show="addingFormModal" isTable title="引用元素表"
  303. widths="84%" @close="addingFormClose" @save="addingFormSave">
  304. <div class="adding-form-dialog-box">
  305. <div class="dialog-tree-box">
  306. <el-scrollbar>
  307. <ElTree ref="addingFormTreeRef"
  308. :load="addingFormTreeLoadNode"
  309. :props="addingFormTreeProps"
  310. accordion
  311. class="hc-tree-node" highlight-current lazy
  312. @node-click="addingFormTreeClick">
  313. </ElTree>
  314. </el-scrollbar>
  315. </div>
  316. <div class="dialog-table-box">
  317. <div class="dialog-search">
  318. <el-autocomplete
  319. v-model="searchTreeTitle" :fetch-suggestions="querySearchTree"
  320. class="block"
  321. clearable
  322. node-key="primaryKeyId"
  323. placeholder="请输入关键词检索"
  324. value-key="title"
  325. @select="searchTreeSelect"/>
  326. </div>
  327. <div class="dialog-table">
  328. <HcTable ref="dialogTableRef" :column="dialogTableColumn" :datas="dialogTableData"
  329. :loading="dialogTableLoading" isCheck
  330. @select="dialogTableSelect"
  331. @select-all="dialogTableSelectAll"
  332. />
  333. </div>
  334. <div class="dialog-pages">
  335. <HcPages :pages="searchFormPage" @change="searchFormPageChange"/>
  336. </div>
  337. </div>
  338. </div>
  339. </HcDialog>
  340. </div>
  341. </template>
  342. <script setup>
  343. import {ref, watch, onMounted, nextTick} from "vue";
  344. import {useAppStore} from "~src/store";
  345. import {useRouter, useRoute} from 'vue-router'
  346. import WbsTree from "./components/WbsTree.vue"
  347. import HcUpload from "./components/division/HcUpload.vue"
  348. import HcTreeData from "./components/division/HcTreeData.vue"
  349. import HcTreeData1 from "./components/division/HcTreeData1.vue"
  350. import DivisionTree from "./components/division/DivisionTree.vue"
  351. import HcTreeNode from "./components/HcTreeNode.vue"
  352. import {isType, getIndex, deepClone, formValidate, utilsArray} from "vue-utils-plus"
  353. import {getStoreData, setStoreData} from '~src/utils/storage'
  354. import {getDictionary} from "~api/other"
  355. import wbsApi from "~api/data-fill/wbs";
  356. import divisionApi from "~api/data-fill/division";
  357. import Draggable from "vuedraggable";
  358. //初始变量
  359. const router = useRouter()
  360. const useRoutes = useRoute()
  361. const useAppState = useAppStore()
  362. const {getObjValue, getArrValue} = isType()
  363. const {isIndex} = utilsArray()
  364. //全局变量
  365. const projectId = ref(useAppState.getProjectId);
  366. const contractId = ref(useAppState.getContractId);
  367. const projectInfo = ref(useAppState.getProjectInfo);
  368. const isCollapse = ref(useAppState.getCollapse)
  369. const contractInfo = ref(useAppState.getContractInfo);
  370. const { contractType } = contractInfo.value;
  371. const classifyType = ref(contractType === 2 ? '2' : '1')
  372. //监听
  373. watch(() => [
  374. useAppState.getCollapse
  375. ], ([Collapse]) => {
  376. isCollapse.value = Collapse
  377. })
  378. //自动展开缓存
  379. const treeAutoExpandKeys = ref(getStoreData('wbsTreeExpandKeys') || [])
  380. //自动展开缓存
  381. const TreeAutoExpandKeys = ref(getStoreData('wbsTreeExpandKeys') || [])
  382. //渲染完成
  383. onMounted(() => {
  384. //setElTreeMenu()
  385. getWbsNodeTypeApi()
  386. getMajorDataTypeApi()
  387. getWbsNodeTableTypeApi()
  388. getTableOwnerTypeApi()
  389. })
  390. const treeLoading = ref(true)
  391. const treeNodeLoading = () => {
  392. treeLoading.value = false
  393. }
  394. //获取节点类型
  395. const nodeTypeData = ref([])
  396. const getWbsNodeTypeApi = async () => {
  397. const {data} = await getDictionary({
  398. code: 'wbs_node_type'
  399. })
  400. //处理数据
  401. let newArr = []
  402. const newData = getArrValue(data)
  403. for (let i = 0; i < newData.length; i++) {
  404. newArr.push({
  405. label: newData[i]['dictValue'],
  406. value: Number(newData[i]['dictKey']),
  407. })
  408. }
  409. nodeTypeData.value = newArr
  410. }
  411. //获取类型名称
  412. const getRowType = (type) => {
  413. const nodeData = nodeTypeData.value
  414. const index = getIndex(nodeData, 'value', type)
  415. return nodeData[index]?.label ?? type
  416. }
  417. //获取资料类型
  418. const majorDataTypeData = ref([])
  419. const getMajorDataTypeApi = async () => {
  420. const {data} = await getDictionary({
  421. code: 'major_data_type'
  422. })
  423. //处理数据
  424. majorDataTypeData.value = getArrValue(data)
  425. }
  426. //获取资料类型名称
  427. const getRowMajorType = (type) => {
  428. if (type) {
  429. const nodeData = majorDataTypeData.value
  430. const index = getIndex(nodeData, 'dictKey', type)
  431. return nodeData[index]?.dictValue ?? type
  432. }
  433. }
  434. //获取表类型数据
  435. const nodeTableTypeData = ref([])
  436. const getWbsNodeTableTypeApi = async () => {
  437. const {data} = await getDictionary({
  438. code: 'table_type'
  439. })
  440. nodeTableTypeData.value = getArrValue(data)
  441. }
  442. //获取表类型
  443. const getRowTableType = (type) => {
  444. if (type > 0) {
  445. const nodeData = nodeTableTypeData.value
  446. const index = getIndex(nodeData, 'dictKey', type)
  447. return nodeData[index]?.dictValue ?? type
  448. } else {
  449. return ''
  450. }
  451. }
  452. //获取表类型数据
  453. const tableOwnerTypeData = ref([])
  454. const getTableOwnerTypeApi = async () => {
  455. const {data} = await getDictionary({
  456. code: 'owner_type'
  457. })
  458. tableOwnerTypeData.value = getArrValue(data)
  459. }
  460. //获取表类型
  461. const getRowTableOwnerType = (type) => {
  462. if (type > 0) {
  463. const nodeData = tableOwnerTypeData.value
  464. const index = getIndex(nodeData, 'dictKey', type)
  465. return nodeData[index]?.dictValue ?? type
  466. } else {
  467. return ''
  468. }
  469. }
  470. //树被点击
  471. const treeNodeInfo = ref({})
  472. const treeItemInfo = ref({})
  473. const treePrimaryKeyId = ref('')
  474. const wbsElTreeClick = ({node, data, keys}) => {
  475. treeNodeInfo.value = node
  476. treeItemInfo.value = data
  477. tableBasicData.value = [data]
  478. setStoreData('wbsTreeExpandKeys', keys)
  479. treeAutoExpandKeys.value = keys || []
  480. if (node.level === 3) {
  481. treePrimaryKeyId.value = data['primaryKeyId']
  482. } else {
  483. treePrimaryKeyId.value = ''
  484. }
  485. if (node.level > 1) {
  486. searchNodeAllTableApi(data['primaryKeyId'])
  487. }
  488. }
  489. //当前节点基础信息
  490. const tableBasicColumn = ref([
  491. {key: 'title', name: '节点名称'},
  492. {key: 'partitionCode', name: '划分编号'},
  493. {key: 'type', name: '节点类型'},
  494. {key: 'majorDataType', name: '资料类型'},
  495. ])
  496. const tableBasicData = ref([])
  497. //标记为隐蔽工程节点
  498. const concealedChange = async () => {
  499. const {primaryKeyId, isConcealedWorksNode} = treeItemInfo.value
  500. if (primaryKeyId) {
  501. const {error, code, msg} = await divisionApi.concealedWorksNnode({
  502. pKeyId: primaryKeyId,
  503. type: isConcealedWorksNode
  504. }, false)
  505. if (!error && code === 200) {
  506. window?.$message?.success(msg)
  507. } else {
  508. window?.$message?.warning(msg)
  509. }
  510. } else {
  511. window?.$message?.warning('请先在左侧选择节点')
  512. }
  513. }
  514. //当前节点工程用表信息
  515. const tableProjectColumn = ref([
  516. {key: 'nodeName', name: '工程用表名称'},
  517. {key: 'tableType', name: '用表类型'},
  518. {key: 'tableOwner', name: '用表单位'},
  519. {key: 'fillRate', name: '填报完整率'},
  520. {key: 'action', name: '操作', width: 100}
  521. ])
  522. const tableProjectData = ref([])
  523. //获取数据
  524. const searchNodeAllTableApi = async (pid) => {
  525. const {error, code, data} = await wbsApi.searchNodeAllTable({
  526. projectId: projectId.value,
  527. contractId: contractId.value,
  528. primaryKeyId: pid
  529. })
  530. if (!error && code === 200) {
  531. tableProjectData.value = getArrValue(data)
  532. } else {
  533. tableProjectData.value = []
  534. }
  535. }
  536. //树菜单配置
  537. const ElTreeMenu = ref([
  538. {icon: 'add-circle', label: '新增节点', key: "add"},
  539. {icon: 'file-copy-2', label: '复制节点', key: "copy"},
  540. {icon: 'draft', label: '修改节点', key: "edit"},
  541. {icon: 'sort-asc', label: '调整排序', key: "sort"},
  542. {icon: 'delete-bin', label: '删除节点', key: "del"}
  543. ])
  544. //树菜单被点击
  545. const ElTreeMenuClick = async ({key, node, data, keys}) => {
  546. treeNodeInfo.value = node
  547. treeItemInfo.value = data
  548. setStoreData('wbsTreeExpandKeys', keys)
  549. if (key === 'add') {
  550. addTreeNodeId.value = data?.id
  551. addTreeNodeOldId.value = data?.oldId
  552. addNodeLoading.value = false
  553. addNodeModal.value = true
  554. } else if (key === 'copy') {
  555. const parent = deepClone(node?.parent?.data || {})
  556. formCopyNodeModel.value = {...deepClone(data), parent: parent}
  557. copyNodeTabKey.value = '1'
  558. copyNodeTable.value = []
  559. copyNodeLoading.value = false
  560. copyNodeModal.value = true
  561. } else if (key === 'edit') {
  562. const parent = deepClone(node?.parent?.data || {})
  563. formEditNodeModel.value = {...deepClone(data), parent: parent}
  564. editNodeModal.value = true
  565. } else if (key === 'sort') {
  566. let nodes = [], childNodes = []
  567. childNodes = node?.parent?.childNodes || []
  568. for (let i = 0; i < childNodes.length; i++) {
  569. const res = childNodes[i]?.data
  570. nodes.push({
  571. id: res?.primaryKeyId,
  572. title: res?.title
  573. })
  574. }
  575. sortNodeData.value = nodes
  576. sortNodeModal.value = true
  577. } else if (key === 'del') {
  578. // delModalClick()
  579. if (data['colorStatus'] === 1 || data['colorStatus'] === 2) {
  580. delModalClick()
  581. } else {
  582. window?.$message?.warning('该节点已存在上报数据,不允许删除')
  583. }
  584. }
  585. }
  586. //编辑节点
  587. const editNodeModal = ref(false)
  588. const formEditNodeRef = ref(null)
  589. const formEditNodeModel = ref({})
  590. const formEditNodeRules = {
  591. title: {
  592. required: true,
  593. trigger: 'blur',
  594. message: "请输入节点名称"
  595. },
  596. }
  597. const editNodeLoading = ref(false)
  598. //保存编辑节点数据
  599. const editNodeClick = async () => {
  600. const validate = await formValidate(formEditNodeRef.value)
  601. if (validate) {
  602. //发起请求
  603. editNodeLoading.value = true
  604. const {primaryKeyId, title, partitionCode} = formEditNodeModel.value
  605. const {error, code} = await wbsApi.wbsTreeUpdateNode({
  606. nodeName: title || '',
  607. pKeyId: primaryKeyId || '',
  608. partitionCode: partitionCode || ''
  609. })
  610. //处理数据
  611. editNodeLoading.value = false
  612. if (!error && code === 200) {
  613. window?.$message?.success('修改成功')
  614. treeItemInfo.value['title'] = title || ''
  615. treeItemInfo.value['partitionCode'] = partitionCode || ''
  616. editNodeModal.value = false
  617. window?.location?.reload() //刷新页面
  618. }
  619. }
  620. }
  621. //复制节点
  622. const copyNodeModal = ref(false)
  623. //复制节点类型tab数据和相关处理
  624. const copyNodeTabKey = ref('1')
  625. const copyNodeTab = ref([
  626. {key: '1', name: '单份复制'},
  627. {key: '2', name: '多份复制'},
  628. {key: '3', name: '复制数据'}
  629. ]);
  630. const copyNodeTabChange = (key) => {
  631. if (key !== copyNodeTabKey.value) {
  632. copyNodeTabKey.value = key;
  633. copyNodeTable.value = []
  634. copyNodeLoading.value = false
  635. }
  636. }
  637. //复制节点变量
  638. const copyNodeLoading = ref(false)
  639. const formCopyNodeModel = ref({})
  640. const copyNodeTable = ref([])
  641. const classifyList = ref([])
  642. //复制树被点击
  643. const copyNodeElTreeClick = ({data}) => {
  644. const TabKey = copyNodeTabKey.value;
  645. const {title, type} = formCopyNodeModel.value;
  646. if (TabKey === '2') {
  647. //1 单位工程,2 分部工程,3 子分部工程,4 分项工程, 5 子分项工程,6 工序
  648. //工序节点不能复制到工序节点下面
  649. // if (type === 6 && (data['type'] === 4 || data['type'] === 5 || data['type'] === 6)) {
  650. // setCopyNodeTable(data, title)
  651. // }
  652. if (type === 6 && (data['type'] === 4 || data['type'] === 5 || data['type'] !== 6)) {
  653. setCopyNodeTable(data, title)
  654. }
  655. if (type === 5 && data['type'] === 4) {
  656. setCopyNodeTable(data, title)
  657. }
  658. if (type === 4 && (data['type'] === 2 || data['type'] === 3)) {
  659. setCopyNodeTable(data, title)
  660. }
  661. if (type === 3 && data['type'] === 2) {
  662. setCopyNodeTable(data, title)
  663. }
  664. if (type === 2 && data['type'] === 1) {
  665. setCopyNodeTable(data, title)
  666. }
  667. if (type === 1 && data['type'] === 1) {
  668. setCopyNodeTable(data, title)
  669. }
  670. } else if (TabKey === '3') {
  671. //限制复制数据不能复制到本身节点下
  672. if (data['id'] !== formCopyNodeModel.value.id) {
  673. // console.log(formCopyNodeModel.value,'formCopyNodeModel.value');
  674. // console.log(data,'data');
  675. // if(data['colorStatus']===1||data['colorStatus']===2){
  676. // // delModalClick()
  677. // }else{
  678. // window?.$message?.warning('该节点已存在上报数据,不允许复制')
  679. // }
  680. if (data['notExsitChild']) {
  681. //限制一个节点不能点击多次
  682. let oldarr = copyNodeTable.value
  683. let result = oldarr.some(item => item.primaryKeyId === data['primaryKeyId']) //true
  684. if (!result) {
  685. setCopyNodeTable(data, data?.title)
  686. }
  687. }
  688. }
  689. }
  690. }
  691. const setCopyNodeTable = (data, title) => {
  692. copyNodeTable.value.push({
  693. title: data?.title || '',
  694. nodeName: title || '',
  695. primaryKeyId: data?.primaryKeyId || ''
  696. })
  697. }
  698. //节点表单
  699. const formCopyNodeModelRef = ref(null)
  700. const formCopyNodeModelRules = {
  701. title: {
  702. required: true,
  703. trigger: "blur",
  704. message: "请输入节点名称"
  705. }
  706. }
  707. //表格节点表单
  708. const copyNodeTableRef = ref(null)
  709. const copyNodeTableRules = {
  710. nodeName: {
  711. required: true,
  712. trigger: "blur",
  713. message: "请输入节点名称"
  714. }
  715. }
  716. //删除选中的节点
  717. const copyNodeTableDel = (index) => {
  718. copyNodeTable.value.splice(index, 1)
  719. }
  720. //复制节点
  721. //复制节点
  722. const copyNodeClick = async () => {
  723. const type = copyNodeTabKey.value
  724. const form = formCopyNodeModel.value
  725. const table = copyNodeTable.value
  726. let classify = ''
  727. let arr = []
  728. if (classifyList.value.length > 0) {
  729. classifyList.value.forEach((item) => {
  730. if (item === '施工') {
  731. arr.push(1)
  732. } else if (item === '监理') {
  733. arr.push(2)
  734. }
  735. })
  736. classify = arr.join(',')
  737. }
  738. //效验数据
  739. if (type === '1') {
  740. const validate = await formValidate(formCopyNodeModelRef.value)
  741. if (validate) await copyContractTreeNode(type, form, [])
  742. } else if (type === '2') {
  743. if (table.length > 0) {
  744. const validate = await formValidate(copyNodeTableRef.value)
  745. if (validate) await copyContractTreeNode(type, form, table)
  746. } else {
  747. window?.$message?.warning('请先在左侧选择要复制到的节点')
  748. }
  749. } else if (type === '3') {
  750. if (table.length > 0 && classify.length > 0) {
  751. await copyContractNodeSubmitBusinessData(form, table, classify)
  752. } else {
  753. window?.$message?.warning('请先在左侧选择要复制的节点或选择所属方')
  754. }
  755. }
  756. }
  757. //单个复制、多份复制请求
  758. const copyContractTreeNode = async (type, form, table) => {
  759. copyNodeLoading.value = true
  760. const {error, code} = await wbsApi.copyContractTreeNode({
  761. copyType: type,
  762. needCopyNodeName: form?.title || '',
  763. needCopyPrimaryKeyId: form?.primaryKeyId || '',
  764. parentPrimaryKeyId: form?.parent?.primaryKeyId || '',
  765. copyBatchToPaths: table
  766. })
  767. //判断状态
  768. copyNodeLoading.value = false
  769. if (!error && code === 200) {
  770. window?.$message?.success('复制成功')
  771. copyNodeModal.value = false
  772. window?.location?.reload() //刷新页面
  773. }
  774. }
  775. //复制数据
  776. const copyContractNodeSubmitBusinessData = async (form, table, classify) => {
  777. copyNodeLoading.value = true
  778. const {error, code} = await wbsApi.copyContractNodeSubmitBusinessData({
  779. needCopyPrimaryKeyId: form?.primaryKeyId || '',
  780. copyBatchToPaths: table,
  781. classify: classify
  782. })
  783. //判断状态
  784. copyNodeLoading.value = false
  785. if (!error && code === 200) {
  786. window?.$message?.success('复制成功')
  787. copyNodeModal.value = false
  788. window?.location?.reload() //刷新页面
  789. }
  790. }
  791. //新增节点
  792. const addNodeModal = ref(false)
  793. const addTreeNodeId = ref('')
  794. const addTreeNodeOldId = ref('')
  795. const addTreeNodeType = ref('1')
  796. //选中的节点
  797. const allSelectedList = ref([])
  798. const halfSelectedList = ref([])
  799. const addTreeNodeCheckChange = (nodes) => {
  800. let NodesArr = [], halfArr = []
  801. //全选数据
  802. const keys = nodes.checkedNodes || []
  803. for (let i = 0; i < keys.length; i++) {
  804. NodesArr.push({
  805. nodeName: keys[i].title,
  806. primaryKeyId: keys[i].primaryKeyId
  807. })
  808. }
  809. allSelectedList.value = NodesArr
  810. //半选数据
  811. const halfNodes = nodes.halfCheckedNodes || []
  812. for (let i = 0; i < halfNodes.length; i++) {
  813. halfArr.push({
  814. nodeName: halfNodes[i].title,
  815. primaryKeyId: halfNodes[i].primaryKeyId
  816. })
  817. }
  818. halfSelectedList.value = halfArr
  819. }
  820. //新增节点
  821. const addNodeLoading = ref(false)
  822. const addNodeClick = async () => {
  823. const keys = allSelectedList.value || []
  824. if (keys.length <= 0) {
  825. window?.$message?.warning('请先选择节点')
  826. } else {
  827. //发起请求
  828. addNodeLoading.value = true
  829. const primaryKeyId = treeItemInfo.value?.primaryKeyId || ''
  830. const {error, code} = await wbsApi.saveContractTreeNode({
  831. projectId: projectId.value,
  832. contractId: contractId.value,
  833. saveType: addTreeNodeType.value,
  834. allSelectedList: allSelectedList.value,
  835. halfSelectedList: halfSelectedList.value,
  836. currentNodePrimaryKeyId: primaryKeyId
  837. })
  838. //判断状态
  839. addNodeLoading.value = false
  840. if (!error && code === 200) {
  841. window?.$message?.success('新增成功')
  842. addNodeModal.value = false
  843. window?.location?.reload() //刷新页面
  844. }
  845. }
  846. }
  847. //删除节点
  848. const delModalClick = () => {
  849. window?.$messageBox?.alert('请谨慎考虑后,确认是否需要删除?', '删除节点', {
  850. showCancelButton: true,
  851. confirmButtonText: '确认删除',
  852. cancelButtonText: '取消',
  853. callback: (action) => {
  854. if (action === 'confirm') {
  855. removeContractTreeNode()
  856. }
  857. }
  858. })
  859. }
  860. const removeContractTreeNode = async () => {
  861. const loadingInstance = window.$loading.service({
  862. fullscreen: true,
  863. text: '删除节点中,请耐心等待...',
  864. background: 'rgba(0, 0, 0, 0.7)'
  865. })
  866. const {error, code} = await wbsApi.removeContractTreeNode({
  867. ids: treeItemInfo.value?.primaryKeyId || ''
  868. })
  869. loadingInstance.close()
  870. if (!error && code === 200) {
  871. window?.$message?.success('删除成功')
  872. window?.location?.reload() //刷新页面
  873. }
  874. }
  875. //调整排序
  876. const sortNodeModal = ref(false)
  877. const sortNodeLoading = ref(false)
  878. const sortNodeData = ref([])
  879. const sortNodeDrag = ref(false)
  880. //向下
  881. const downSortClick = (index) => {
  882. const indexs = index + 1
  883. const data = sortNodeData.value || []
  884. if (indexs !== data.length) {
  885. const tmp = data.splice(indexs, 1);
  886. sortNodeData.value.splice(index, 0, tmp[0]);
  887. } else {
  888. window?.$message?.warning('已经处于置底,无法下移')
  889. }
  890. }
  891. //向上
  892. const upSortClick = (index) => {
  893. const data = sortNodeData.value || []
  894. if (index !== 0) {
  895. const tmp = data.splice(index - 1, 1);
  896. sortNodeData.value.splice(index, 0, tmp[0]);
  897. } else {
  898. window?.$message?.warning('已经处于置顶,无法上移')
  899. }
  900. }
  901. //确认排序
  902. const sortNodeClick = async () => {
  903. const sortList = [];
  904. const nodes = sortNodeData.value || []
  905. nodes.forEach(item => {
  906. sortList.push(item?.id)
  907. })
  908. //发起请求
  909. sortNodeLoading.value = true
  910. const {error, code} = await wbsApi.diySortTreeNode({sortList})
  911. sortNodeLoading.value = false
  912. //判断状态
  913. if (!error && code === 200) {
  914. window?.$message?.success('保存成功')
  915. sortNodeModal.value = false
  916. window?.location?.reload() //刷新页面
  917. }
  918. }
  919. //导入模板
  920. const uploadRef = ref(null)
  921. const importTempModal = ref(false)
  922. const toImportTempClick = () => {
  923. importTempModal.value = true
  924. getContractInfoTreeApi()
  925. }
  926. //导入类型
  927. const importRadio = ref(1)
  928. const importRadioData = ref([
  929. {key: 1, name: '路基工程'},
  930. {key: 2, name: '路面工程'},
  931. {key: 3, name: '桥梁工程'},
  932. {key: 4, name: '机电工程'},
  933. {key: 5, name: '绿化工程'},
  934. {key: 6, name: '隧道工程'},
  935. {key: 7, name: '声屏障工程'},
  936. {key: 8, name: '交通与安全工程'},
  937. {key: 9, name: '特大斜拉桥、特大悬索桥'},
  938. ])
  939. const isSplicingNumber = ref(0)
  940. //上传文件被改变
  941. const uploadFile = ref(null)
  942. const uploadChange = (file) => {
  943. uploadFile.value = file
  944. }
  945. //上传中
  946. const uploadLoading = ref(false)
  947. const uploadprogress = (state) => {
  948. console.log(state)
  949. uploadLoading.value = state
  950. }
  951. //上传完成
  952. const matchedData = ref([])
  953. const unmatchedData = ref([])
  954. const uploadFinished = ({type, data}) => {
  955. uploadRef.value?.clearFiles()
  956. if (type === 'success') {
  957. uploadFile.value = null
  958. window?.$message?.success('导入成功');
  959. matchedData.value = getArrValue(data['matchedData'])
  960. unmatchedData.value = getArrValue(data['unmatchedData'])
  961. } else {
  962. uploadFile.value = null
  963. matchedData.value = []
  964. unmatchedData.value = []
  965. }
  966. }
  967. //关闭导入弹窗
  968. const importTempModalClose = () => {
  969. uploadFile.value = null
  970. importTempModal.value = false
  971. }
  972. //确认导入
  973. const importTempFolder = () => {
  974. if (uploadFile.value) {
  975. uploadRef.value?.submit()
  976. } else {
  977. window?.$message?.warning('请先选择文件');
  978. }
  979. }
  980. //关联被点击
  981. const relationModal = ref(false)
  982. const relationItemInfo = ref({})
  983. const unmatchedTreeTap = ({data}) => {
  984. relationItemInfo.value = data
  985. relationModal.value = true
  986. }
  987. //获取导入树
  988. const unmatchedTreeData = ref([])
  989. const getContractInfoTreeApi = async () => {
  990. const {error, code, data} = await divisionApi.getContractInfoTree({
  991. projectId: projectId.value,
  992. contractId: contractId.value,
  993. wbsId: ''
  994. })
  995. //判断状态
  996. if (!error && code === 200) {
  997. unmatchedTreeData.value = getArrValue(data)
  998. } else {
  999. unmatchedTreeData.value = []
  1000. }
  1001. }
  1002. //关联树
  1003. const divisionTreeItemInfo = ref({})
  1004. const divisionTreeClick = ({data}) => {
  1005. divisionTreeItemInfo.value = data
  1006. }
  1007. //确认关联
  1008. const relationLoading = ref(false)
  1009. const relationSaveClick = () => {
  1010. const item = relationItemInfo.value
  1011. const info = divisionTreeItemInfo.value
  1012. const primaryKeyId = info?.primaryKeyId ?? ''
  1013. if (!primaryKeyId) {
  1014. window?.$message?.warning('请先选择一个树节点')
  1015. } else {
  1016. setImportRelationApi({
  1017. pKeyIdOld: info?.primaryKeyId,
  1018. wbsTreeContractVO: {
  1019. ...item,
  1020. id: ''
  1021. }
  1022. })
  1023. }
  1024. }
  1025. const setImportRelationApi = async (form) => {
  1026. relationLoading.value = true
  1027. const {error, code} = await divisionApi.setImportRelation(form)
  1028. relationLoading.value = false
  1029. if (!error && code === 200) {
  1030. window.$message?.success('关联成功')
  1031. relationModal.value = false
  1032. }
  1033. }
  1034. //下载模板
  1035. const downloadXlsx = () => {
  1036. window.open('https://bladex-test-info.oss-cn-chengdu.aliyuncs.com//upload/20221017/854463fdfdf90843e6783fbcb4d7d00c.xlsx', '_blank')
  1037. }
  1038. //返回上页
  1039. const toBackClick = () => {
  1040. router.push({path: '/data-fill/wbs'})
  1041. }
  1042. //添加独立表单
  1043. const addingFormModal = ref(false)
  1044. const addingFormClick = () => {
  1045. const {isLeaf} = treeNodeInfo.value
  1046. if (isLeaf) {
  1047. addingFormLoading.value = false
  1048. addingFormModal.value = true
  1049. } else {
  1050. window?.$message?.warning('请先选择一个最子级的节点')
  1051. }
  1052. }
  1053. //删除当前节点用表
  1054. const deltableexcel = async (row) => {
  1055. console.log(row, 'row');
  1056. if (row['isEle'] === '1') {
  1057. if (row['pdfUrl'] !== '') {
  1058. window?.$messageBox?.alert('该表已填写数据' + ',请谨慎考虑后,确认是否需要删除?', '删除', {
  1059. showCancelButton: true,
  1060. confirmButtonText: '确认删除',
  1061. cancelButtonText: '取消',
  1062. callback: async (action) => {
  1063. if (action === 'confirm') {
  1064. const {error, code, msg} = await divisionApi.removeWbsTreeContract({
  1065. id: row.pkeyId,
  1066. stats: 0
  1067. })
  1068. if (!error && code === 200) {
  1069. window?.$message?.success('删除成功')
  1070. window?.location?.reload() //刷新页面
  1071. } else {
  1072. window?.$message?.warning(msg)
  1073. }
  1074. }
  1075. }
  1076. })
  1077. } else {
  1078. const {error, code, msg} = await divisionApi.removeWbsTreeContract({id: row.pkeyId, stats: 0})
  1079. if (!error && code === 200) {
  1080. window?.$message?.success('删除成功')
  1081. window?.location?.reload() //刷新页面
  1082. } else {
  1083. window?.$message?.warning(msg)
  1084. }
  1085. }
  1086. } else {
  1087. window?.$message?.warning('该表不允许删除')
  1088. }
  1089. }
  1090. //树配置
  1091. const addingFormTreeRef = ref(null)
  1092. const addingFormTreeProps = {
  1093. label: 'title',
  1094. children: 'children',
  1095. isLeaf: 'isLeaf'
  1096. }
  1097. //树加载
  1098. const addingFormTreeLoadNode = async (node, resolve) => {
  1099. if (node.level === 0) {
  1100. const resData = await tabTypeLazyTree()
  1101. resolve(resData?.data)
  1102. } else {
  1103. const resData = await tabTypeLazyTree(node?.data?.primaryKeyId, '', false, {
  1104. current: 1, size: 2000,
  1105. })
  1106. resolve(resData?.data)
  1107. }
  1108. }
  1109. //树被点击
  1110. const addingFormTreeItem = ref({})
  1111. const selectItems = ref([])
  1112. const selectItem = ref({})
  1113. const selectIds = ref([])
  1114. const addingFormTreeClick = async (data, node) => {
  1115. searchTreeTitle.value = ''
  1116. addingFormTreeItem.value = data
  1117. dialogTableData.value = []
  1118. searchFormPage.value.current = 1
  1119. console.log(addingFormTreeItem.value.primaryKeyId, 'addingFormTreeItem.value');
  1120. if (node?.level === 1) {
  1121. getDialogTableData().then()
  1122. } else if (node?.level === 2) {
  1123. searchFormPage.value.total = 1
  1124. dialogTableData.value = [data]
  1125. nextTick(() => {
  1126. dialogTableRef.value?.toggleRowSelection(data, true);
  1127. })
  1128. selectItems.value.push(data)
  1129. }
  1130. }
  1131. //搜索
  1132. const searchTreeTitle = ref('')
  1133. const querySearchTree = async (key, resolve) => {
  1134. if (key) {
  1135. const primaryKeyId = addingFormTreeItem.value?.primaryKeyId ?? ''
  1136. const size = 100000
  1137. const {data} = await divisionApi.tabTypeLazyTree({
  1138. projectId: projectId.value,
  1139. contractId: contractId.value,
  1140. titleName: key,
  1141. current: 1,
  1142. size: 10000
  1143. })
  1144. resolve(data?.records)
  1145. } else {
  1146. resolve([])
  1147. }
  1148. }
  1149. const searchTreeSelect = (item) => {
  1150. console.log("searchTreeSelect")
  1151. dialogTableRef.value?.clearSelection()
  1152. dialogTableKeys.value = []
  1153. dialogTableData.value = [item]
  1154. selectItems.value = [item]
  1155. nextTick(() => {
  1156. dialogTableRef.value?.toggleRowSelection(item, true);
  1157. })
  1158. searchFormPage.value.current = 1
  1159. searchFormPage.value.total = 0
  1160. }
  1161. //分页
  1162. const searchFormPage = ref({current: 1, size: 20, total: 0})
  1163. const searchFormPageChange = ({current, size}) => {
  1164. searchFormPage.value.current = current
  1165. searchFormPage.value.size = size
  1166. getDialogTableData()
  1167. }
  1168. //表格数据
  1169. const dialogTableRef = ref(null)
  1170. const dialogTableColumn = ref([
  1171. {key: 'title', name: '表单名称'},
  1172. {key: 'tabType', name: '元素表类型'},
  1173. {key: 'elementTotal', name: '元素总量'},
  1174. {key: 'tabOwner', name: '所属方'},
  1175. {key: 'fillRate', name: '填报率'}
  1176. ])
  1177. const dialogTableData = ref([])
  1178. const dialogTableLoading = ref(false)
  1179. const getDialogTableData = async () => {
  1180. //处理初始数据
  1181. dialogTableLoading.value = true
  1182. dialogTableRef.value?.clearSelection()
  1183. dialogTableKeys.value = []
  1184. const primaryKeyId = addingFormTreeItem.value?.primaryKeyId ?? ''
  1185. const searchTitle = searchTreeTitle.value ?? ''
  1186. //获取数据
  1187. const resData = await tabTypeLazyTree(primaryKeyId, searchTitle, true, true)
  1188. const records = getArrValue(resData?.data)
  1189. //处理返回的数据
  1190. dialogTableData.value = records
  1191. dialogTableLoading.value = false
  1192. if (records.length > 0) {
  1193. searchFormPage.value.total = resData.total || 0
  1194. //表格勾选回显
  1195. selectItems.value.forEach((item) => {
  1196. dialogTableData.value.forEach((item1) => {
  1197. if (item.id === item1.id) {
  1198. nextTick(() => {
  1199. dialogTableRef.value?.toggleRowSelection(item1, true);
  1200. })
  1201. }
  1202. })
  1203. })
  1204. } else {
  1205. searchFormPage.value.total = 0
  1206. }
  1207. }
  1208. //多选
  1209. const dialogTableKeys = ref([]);
  1210. // 全选
  1211. const dialogTableSelectAll = (rows) => {
  1212. if (rows.length) { /* 全选 */
  1213. if (selectItems.value.length <= 0) {
  1214. rows.forEach(row => {
  1215. selectItems.value.push(row)
  1216. })
  1217. } else {
  1218. rows.forEach(row => {
  1219. const flag = selectItems.value.filter(e => e.id === row.id)
  1220. if (flag.length <= 0) {
  1221. selectItems.value.push(row)
  1222. }
  1223. })
  1224. }
  1225. } else { /* 反选-清空当前列表数据 */
  1226. dialogTableData.value.forEach(row => {
  1227. // 取消选中时过滤
  1228. selectItems.value = selectItems.value.filter(e => e.id !== row.id)
  1229. })
  1230. }
  1231. }
  1232. const dialogTableSelect = ({selection, row}) => {
  1233. dialogTableKeys.value = selection
  1234. const flag = selectItems.value.filter(e => e.id === row.id)
  1235. if (flag.length <= 0) { /* 不存在表示是选中,勾选时添加 */
  1236. selectItems.value.push(row)
  1237. } else {
  1238. // 取消选中时过滤
  1239. selectItems.value = selectItems.value.filter(e => e.id !== row.id)
  1240. }
  1241. console.log(selectItems.value, "dialogTableSelect selectItems")
  1242. }
  1243. //获取数据
  1244. const tabTypeLazyTree = async (parentId = '12345678910', titleName = '', search = false, form = {}, size) => {
  1245. let obj = {}, searchObj = {}
  1246. if (parentId) obj.parentId = parentId
  1247. if (titleName) obj.titleName = titleName
  1248. if (search) searchObj = searchFormPage.value
  1249. //发起请求
  1250. const {data} = await divisionApi.tabTypeLazyTree({
  1251. projectId: projectId.value,
  1252. contractId: contractId.value,
  1253. ...obj,
  1254. ...searchObj,
  1255. ...form
  1256. })
  1257. const records = getArrValue(data?.records)
  1258. records.forEach(item => {
  1259. item.isLeaf = !item.hasChildren
  1260. })
  1261. return {data: records, total: data?.total}
  1262. }
  1263. //保存
  1264. const addingFormLoading = ref(false)
  1265. const addingFormSave = async () => {
  1266. // const rows = dialogTableKeys.value
  1267. console.log(dialogTableKeys.value, "addingFormSave")
  1268. const rows = selectItems.value
  1269. console.log(rows, 'rows');
  1270. if (rows.length > 0) {
  1271. addingFormLoading.value = true
  1272. const {primaryKeyId} = treeItemInfo.value
  1273. const ids = rowsToId(rows, 'primaryKeyId')
  1274. const arrids = ids.split(',')
  1275. let newStr = [...new Set(arrids)].join(',');
  1276. // console.log(newStr,'ids');
  1277. //发起请求
  1278. const {error, code} = await divisionApi.addWbsContractInfo({
  1279. projectId: projectId.value,
  1280. contractId: contractId.value,
  1281. nodeId: primaryKeyId,
  1282. primaryKeyIds: newStr
  1283. // primaryKeyIds: ids
  1284. })
  1285. //处理结果
  1286. addingFormLoading.value = false
  1287. if (!error && code === 200) {
  1288. window.$message?.success('操作成功')
  1289. addingFormModal.value = false
  1290. window?.location?.reload() //刷新页面
  1291. }
  1292. } else {
  1293. window.$message?.warning('请先勾选数据')
  1294. }
  1295. }
  1296. //关闭
  1297. const addingFormClose = () => {
  1298. addingFormModal.value = false
  1299. dialogTableKeys.value = []
  1300. }
  1301. //拼接ID
  1302. const rowsToId = (rows, key = 'id') => {
  1303. return rows.map((obj) => {
  1304. return obj[key];
  1305. }).join(",")
  1306. }
  1307. //左右拖动,改变树形结构宽度
  1308. const leftWidth = ref(382);
  1309. const onmousedown = () => {
  1310. const leftNum = isCollapse.value ? 142 : 272
  1311. document.onmousemove = (ve) => {
  1312. let diffVal = ve.clientX - leftNum;
  1313. if (diffVal >= 310 && diffVal <= 900) {
  1314. leftWidth.value = diffVal;
  1315. }
  1316. }
  1317. document.onmouseup = () => {
  1318. document.onmousemove = null;
  1319. document.onmouseup = null;
  1320. }
  1321. }
  1322. </script>
  1323. <style lang="scss" scoped>
  1324. @import "../../styles/data-fill/division.scss";
  1325. </style>