add-excel.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. <template>
  2. <hc-dialog v-model="isShow" ui="hc-exctab-exceltab-add-excel" :title="type" widths="800px" :padding="false" @close="dialogClose">
  3. <div class="relative h-80px">
  4. <el-form ref="formRef" :model="formModel" :rules="formRules" label-position="top" label-width="auto">
  5. <el-row :gutter="14">
  6. <el-col :span="12">
  7. <el-form-item label="清表名称:" prop="nodeName">
  8. <el-input v-model="formModel.nodeName" placeholder="请输入清表名称" />
  9. </el-form-item>
  10. </el-col>
  11. <el-col :span="12">
  12. <el-form-item label="清表类型:" prop="tabType">
  13. <el-select v-model="formModel.tabType" filterable block placeholder="请选择清表类型">
  14. <el-option v-for="item in excelTypeData" :key="item.value" :label="item.label" :value="item.value" />
  15. </el-select>
  16. </el-form-item>
  17. </el-col>
  18. </el-row>
  19. </el-form>
  20. </div>
  21. <div class="hc-exctab-exceltab-add-excel-middle">
  22. <el-row :gutter="14" class="h-full">
  23. <el-col :span="12" class="h-full">
  24. <div class="left-card h-full">
  25. <div class="select">
  26. <el-select v-model="formModel.wbsId" filterable block placeholder="请选择WBS模板" @change="wbsModelChange">
  27. <el-option v-for="item in wbsModel" :key="item.id" :label="item.wbsName" :value="item.id" />
  28. </el-select>
  29. </div>
  30. <div v-loading="treeLoading" class="tree">
  31. <el-scrollbar>
  32. <el-tree v-if="isWbsTree" :props="wbsTreeProps" :load="wbsTreeLoad" lazy accordion highlight-current @node-click="wbsTreeClick" />
  33. </el-scrollbar>
  34. </div>
  35. </div>
  36. </el-col>
  37. <el-col :span="12" class="h-full">
  38. <div class="right-card h-full">
  39. <hc-table :column="tableColumn" :datas="tableData" :is-index="false" :is-current-row="false">
  40. <template #action="{ row }">
  41. <el-link v-if="row.isLinkTable !== 2" type="primary" @click="rowRelation(row)">关联</el-link>
  42. <el-link v-if="row.isLinkTable === 2" type="warning" @click="rowCancel(row)">取消关联</el-link>
  43. </template>
  44. </hc-table>
  45. </div>
  46. </el-col>
  47. </el-row>
  48. </div>
  49. <template #footer>
  50. <el-button hc-btn @click="dialogClose">取消</el-button>
  51. <el-button hc-btn type="primary" :loading="submitLoading" @click="dialogSubmit">提交</el-button>
  52. </template>
  53. </hc-dialog>
  54. </template>
  55. <script setup>
  56. import { nextTick, ref, watch } from 'vue'
  57. import { getDictionaryData } from '~uti/tools'
  58. import { formValidate, getArrValue, getObjValue, isNullES } from 'js-fast-way'
  59. import mainApi from '~api/exctab/exceltab'
  60. const props = defineProps({
  61. info: {
  62. type: Object,
  63. default: () => ({}),
  64. },
  65. type: {
  66. type: String,
  67. default: '新增',
  68. },
  69. })
  70. //事件
  71. const emit = defineEmits(['finish', 'close'])
  72. //双向绑定
  73. const isShow = defineModel('modelValue', {
  74. default: false,
  75. })
  76. //监听可否编辑
  77. const dataInfo = ref(props.info)
  78. watch(() => props.info, (data) => {
  79. dataInfo.value = data
  80. }, { immediate: true, deep: true })
  81. //监听显示
  82. watch(isShow, (val) => {
  83. if (val) getInfoData()
  84. })
  85. //处理数据
  86. const wbsMiddle = ref(false)
  87. const excelTypeData = ref([])
  88. const getInfoData = async () => {
  89. const data = getObjValue(dataInfo.value)
  90. console.log(data)
  91. if (data.fileType === 3) {
  92. wbsMiddle.value = false
  93. } else {
  94. wbsMiddle.value = true
  95. getWbsTypeList().then() //wbs模板名称
  96. }
  97. //获取清表类型
  98. const types = await getDictionaryData('sys_excltab_type', true)
  99. types.forEach(item => {
  100. item.value = Number(item.value)
  101. })
  102. excelTypeData.value = types
  103. //处理表单默认数据
  104. if (props.type === '新增') {
  105. formModel.value = { parentId: data.id }
  106. } else {
  107. formModel.value = { id: data.id }
  108. }
  109. }
  110. //清表编辑 wbs 下拉框选择
  111. const wbsModel = ref([])
  112. const getWbsTypeList = async () => {
  113. const { data } = await mainApi.getWbsTypeList({ wbstype: 2 })
  114. wbsModel.value = getArrValue(data)
  115. }
  116. //选择WBS模板
  117. const isWbsTree = ref(false)
  118. const wbsModelChange = () => {
  119. isWbsTree.value = false
  120. tableData.value = []
  121. tableList.value = []
  122. const wbsId = formModel.value.wbsId
  123. wbsModel.value.forEach(item => {
  124. if (item.id === wbsId) {
  125. formModel.value.wbsType = item.wbsType
  126. }
  127. })
  128. nextTick(() => {
  129. isWbsTree.value = true
  130. })
  131. }
  132. //树
  133. const wbsTreeProps = {
  134. label: 'nodeName',
  135. isLeaf: (item) => {
  136. return !item.hasChildren
  137. },
  138. }
  139. //懒加载树
  140. const treeLoading = ref(false)
  141. const wbsTreeLoad = async (node, resolve) => {
  142. treeLoading.value = true
  143. const parentId = node.level === 0 ? 0 : node.data.id
  144. const { wbsId, wbsType } = formModel.value
  145. const { data } = await mainApi.wbsTree({
  146. parentId, wbsId, wbsType,
  147. })
  148. treeLoading.value = false
  149. resolve(getArrValue(data))
  150. }
  151. //树节点被点击
  152. const wbsForm = ref({})
  153. const wbsTreeClick = ({ id, type, nodeName }) => {
  154. wbsForm.value = { id, wbsType: type, wbsName: nodeName }
  155. const form = formModel.value
  156. if (tableList.value.length <= 0) {
  157. selectByNodeTable(id, type, form.id, form.wbsId)
  158. } else {
  159. let tag = true
  160. tableList.value.forEach((item) => {
  161. if (item.id === id) {
  162. tableData.value = item.arrs
  163. tag = false
  164. }
  165. })
  166. if (tag) {
  167. selectByNodeTable(id, type, form.id, form.wbsId)
  168. }
  169. }
  170. }
  171. //获取数据
  172. const selectByNodeTable = async (id, type, formId, wbsId) => {
  173. const { data } = await mainApi.selectByNodeTable({
  174. id,
  175. wbsType: type ?? '',
  176. liunxId: formId ?? '',
  177. projectid: wbsId ?? '',
  178. })
  179. const res = getArrValue(data)
  180. res.forEach(item => {
  181. item.changeTable = item.isLinkTable
  182. })
  183. tableData.value = res
  184. }
  185. //基础表单
  186. const formRef = ref(null)
  187. const formModel = ref({})
  188. const formRules = {
  189. nodeName: {
  190. required: true,
  191. trigger: 'blur',
  192. message: '请输入清表名称',
  193. },
  194. tabType: {
  195. required: true,
  196. trigger: 'blur',
  197. message: '请选择清表类型',
  198. },
  199. }
  200. //表格
  201. const tableColumn = [
  202. { key: 'tableName', name: '表名' },
  203. { key: 'action', name: '操作', width: 80, align: 'center' },
  204. ]
  205. const tableData = ref([])
  206. const tableList = ref([])
  207. //关联
  208. const rowRelation = (row) => {
  209. row.isLinkTable = 2
  210. setTableList()
  211. }
  212. //取消关联
  213. const rowCancel = (row) => {
  214. row.isLinkTable = 1
  215. setTableList()
  216. }
  217. //处理数据
  218. const setTableList = () => {
  219. const form = wbsForm.value
  220. let tap = tableList.value.find((item) => {
  221. return item.id === form.id
  222. })
  223. if (!tap) {
  224. tableList.value.push({
  225. id: form.id,
  226. wbsType: form.wbsType,
  227. wbsName: form.wbsName,
  228. arrs: tableData.value,
  229. })
  230. }
  231. }
  232. //提交
  233. const submitLoading = ref(false)
  234. const dialogSubmit = async () => {
  235. const isValidate = await formValidate(formRef.value)
  236. if (!isValidate) return false
  237. submitLoading.value = true
  238. let linkDataInfo = []
  239. const list = tableList.value
  240. if (list.length > 0) {
  241. list.forEach(item => {
  242. let linkIds = ''
  243. item.arrs.forEach(data => {
  244. if (data.isLinkTable !== data.changeTable) {
  245. linkIds = `${linkIds}${linkIds !== '' ? ',' : ''}${data.pkeyId}_${data.isLinkTable}`
  246. }
  247. })
  248. if (!isNullES(linkIds)) {
  249. linkDataInfo.push({
  250. id: item.id,
  251. linkIds: linkIds,
  252. wbsName: item.wbsName,
  253. wbsType: item.wbsType,
  254. })
  255. }
  256. })
  257. }
  258. let res = {}
  259. const form = formModel.value
  260. if (!isNullES(form.parentId) && isNullES(form.id)) {
  261. res = await mainApi.savaDataInfo({
  262. nodeName: form.nodeName,
  263. tabType: form.tabType,
  264. parentId: form.parentId,
  265. linkDataInfo: linkDataInfo,
  266. })
  267. } else {
  268. res = await mainApi.savaDataInfo({
  269. nodeName: form.nodeName,
  270. tabType: form.tabType,
  271. id: form.id,
  272. linkDataInfo: linkDataInfo,
  273. })
  274. }
  275. const { code } = res
  276. submitLoading.value = false
  277. if (code === 200) {
  278. window.$message.success('保存成功')
  279. dialogClose()
  280. emit('finish')
  281. }
  282. }
  283. //关闭弹窗
  284. const dialogClose = () => {
  285. isShow.value = false
  286. submitLoading.value = false
  287. wbsForm.value = {}
  288. formModel.value = {}
  289. tableList.value = []
  290. tableData.value = []
  291. emit('close')
  292. }
  293. </script>
  294. <style lang="scss">
  295. .el-overlay-dialog .el-dialog.hc-new-dialog.hc-exctab-exceltab-add-excel .el-dialog__body{
  296. height: 660px;
  297. padding: 12px 0;
  298. }
  299. .hc-exctab-exceltab-add-excel-middle {
  300. position: relative;
  301. height: calc(100% - 80px);
  302. overflow: hidden;
  303. .left-card {
  304. position: relative;
  305. border: 1px solid gainsboro;
  306. border-radius: 3px;
  307. .select {
  308. position: relative;
  309. display: flex;
  310. justify-content: center;
  311. align-items: center;
  312. padding: 6px;
  313. height: 45px;
  314. border-bottom: 1px solid gainsboro;
  315. }
  316. .tree {
  317. position: relative;
  318. height: calc(100% - 45px);
  319. padding: 6px;
  320. }
  321. }
  322. .right-card {
  323. position: relative;
  324. }
  325. }
  326. </style>