dash.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. <template>
  2. <div class="full-height full-width flex flex-col">
  3. <div class="flex flex-col padding white-bg">
  4. <div class="flex flex-align-center tip">
  5. <el-icon class="ml-20" color="#BC002D">
  6. <WarningFilled/>
  7. </el-icon>
  8. <span class="ml-5">项目总投资额<span
  9. class="main-color bold">{{ num ? Number.parseFloat(num).toLocaleString() : '-' }}</span>万元</span>
  10. </div>
  11. <div class="flex ml-20 hide-scrollbar" style="overflow-x: scroll;width: 86vw;"
  12. v-show='numList && numList.length > 0'>
  13. <div v-for="(item,index) in numList" :key='item.id' :class="active === index ? 'total-s' : 'total'"
  14. class="flex flex-center flex-justify-between mt-20 bold font-16 pointer" @click='switchTab(item,index)'
  15. >
  16. <span class=" sp">{{ item.name }}</span>
  17. <span class=" sp1 ">{{ item.number }}<span class="grey font-13">个</span></span>
  18. </div>
  19. </div>
  20. <div class='flex flex-center flex-justify-start'>
  21. <base-button class="ml-20 mt-20" icon="Plus" title="新增"
  22. @click="showAdd = true"/>
  23. <base-button class="ml-20 mt-20" icon="el-icon-upload" title="数据导入"
  24. @click="diaType = 0"/>
  25. <base-button class="ml-20 mt-20" icon="el-icon-download" title="数据导出"
  26. @click="diaType = 1"/>
  27. <base-button class="ml-20 mt-20" type="0" icon="el-icon-download" title="汇总数据导出"
  28. @click="diaType = 2"/>
  29. </div>
  30. </div>
  31. <avue-crud ref="crud"
  32. v-model="form"
  33. v-model:page="page"
  34. :before-open="beforeOpen"
  35. :data="data"
  36. :option="option"
  37. :permission="permissionList"
  38. :table-loading="loading"
  39. class="curd"
  40. @row-del="rowDel"
  41. @tree-load="treeLoad"
  42. @current-change="currentChange"
  43. @size-change="sizeChange"
  44. @refresh-change="refreshChange"
  45. @on-load="onLoad">
  46. <template #menu="{row}">
  47. <el-button icon="Upload" type='primary' text @click="track(row)"> {{
  48. row.isReport === 1 ? "已经上报" : "项目上报"
  49. }}
  50. </el-button>
  51. </template>
  52. </avue-crud>
  53. <!-- 新增-->
  54. <el-dialog v-model="showAdd"
  55. append-to-body
  56. center
  57. title="新增项目"
  58. width="35%">
  59. <div v-loading='addLoading'>
  60. <el-form ref='form' :model="projectForm" class="lab mt-20" label-width="100px" :rules="rules">
  61. <div class="flex flex-center flex-col mr-20">
  62. <el-form-item class="full-width" label="项目名称" prop='name'>
  63. <el-input
  64. v-model="projectForm.name"
  65. clearable
  66. placeholder="输入项目名称"
  67. />
  68. </el-form-item>
  69. <el-form-item class="full-width" label="项目总投" prop='totalAmount'>
  70. <el-input
  71. v-model="projectForm.totalAmount"
  72. clearable
  73. placeholder="输入项目总投(万元)"
  74. >
  75. <template #append>(万元)</template>
  76. </el-input>
  77. </el-form-item>
  78. <el-form-item class="full-width" label="项目类型" prop='projectType'>
  79. <el-select
  80. v-model="projectForm.projectType"
  81. clearable
  82. placeholder="选择项目类型"
  83. style="width: 100%"
  84. >
  85. <el-option
  86. v-for="item in typeList"
  87. :key="item.id"
  88. :label="item.name"
  89. :value="item.id"
  90. />
  91. </el-select>
  92. </el-form-item>
  93. <el-form-item class="full-width" label="项目标签" prop='tags'>
  94. <el-select
  95. v-model="projectForm.tags"
  96. clearable
  97. placeholder="选择项目标签"
  98. style="width: 100%"
  99. >
  100. <el-option
  101. v-for="item in tagsList"
  102. :key="item.dictKey"
  103. :label="item.dictValue"
  104. :value="item.dictKey"
  105. />
  106. </el-select>
  107. </el-form-item>
  108. <el-form-item class="full-width" label="建设内容">
  109. <el-input
  110. v-model="projectForm.introduction"
  111. :rows="6"
  112. clearable
  113. placeholder="输入项目建设内容"
  114. type="textarea"
  115. />
  116. </el-form-item>
  117. <div class="flex flex-center mt-10">
  118. <base-button class="mr-20" icon="Close" title="取消" type="0" @click="showAdd = false"/>
  119. <base-button icon="Check" title="保存" @click="projectSave"/>
  120. </div>
  121. </div>
  122. </el-form>
  123. </div>
  124. </el-dialog>
  125. <form-dialog :dialogType="diaType" @close="diaType = -1" @export='exportExcel'/>
  126. <summary-dialog :dialogType="diaType" @close="diaType = -1"/>
  127. </div>
  128. </template>
  129. <script>
  130. import BaseButton from '../../../components/base-button.vue'
  131. import permissionStore from '@/store/permission.js'
  132. import {vaildData} from '@/utils/tools.js'
  133. import formDialog from '@/views/home/component/form_dialog.vue'
  134. import {getLazyList} from '@/api/project/index.js'
  135. import summaryDialog from "@/views/home/component/summary_dialog.vue";
  136. export default {
  137. name: 'dash',
  138. components: {BaseButton, formDialog, summaryDialog},
  139. setup() {
  140. const permissions = permissionStore()
  141. return {permissions}
  142. },
  143. data() {
  144. return {
  145. disable: false,
  146. showAdd: false,
  147. active: 0,
  148. loading: false,
  149. addLoading: false,
  150. data: [],
  151. form: {},
  152. option: {
  153. refreshBtn: false,
  154. tip: false,
  155. lazy: true,
  156. columnBtn: false,
  157. searchShow: true,
  158. selection: true,
  159. editBtn: true,
  160. editBtnText: '资料管理',
  161. editBtnIcon: 'Document',
  162. addBtn: false,
  163. delBtn: true,
  164. border: true,
  165. index: true,
  166. align: 'center',
  167. viewBtn: true,
  168. viewBtnText: '详情',
  169. menuWidth: 380,
  170. dialogClickModal: false,
  171. column: [
  172. {
  173. label: '项目名称',
  174. prop: 'name',
  175. addDisplay: false,
  176. editDisplay: false
  177. },
  178. {
  179. label: '项目情况',
  180. prop: 'projectStage',
  181. type: 'select',
  182. width: 180,
  183. dicUrl: '/api/blade-system/dict-biz/dictionary?code=project-situation',
  184. props: {
  185. label: 'dictValue',
  186. value: 'dictKey'
  187. }
  188. },
  189. {
  190. label: '项目总投资(万元)',
  191. prop: 'totalAmount',
  192. width: 180,
  193. type: 'number',
  194. precision: 2,
  195. formatter: (val, value, label) => {
  196. return val.totalAmount.toLocaleString()
  197. }
  198. },
  199. {
  200. label: '股(科)室',
  201. prop: 'createDeptName',
  202. width: 180
  203. },
  204. {
  205. label: '子项目数量',
  206. prop: 'lot',
  207. width: 180
  208. },
  209. {
  210. label: '是否开工',
  211. prop: 'isStart',
  212. width: 180,
  213. dicData: [
  214. {
  215. label: '否',
  216. value: 0
  217. },
  218. {
  219. label: '是',
  220. value: 1
  221. }
  222. ]
  223. },
  224. {
  225. label: '项目类型',
  226. prop: 'projectTypeName',
  227. width: 180
  228. },
  229. {
  230. label: '创建时间',
  231. prop: 'createTime',
  232. width: 180
  233. }]
  234. },
  235. page: {
  236. size: 10,
  237. current: 1,
  238. total: 0
  239. },
  240. stage: [],
  241. numList: [],
  242. typeList: [],
  243. tagsList: [],
  244. num: '',
  245. projectForm: {
  246. name: '',
  247. totalAmount: '',
  248. projectType: '',
  249. tags: '',
  250. introduction: ''
  251. },
  252. rules: {
  253. name: [
  254. {required: true, message: '请输入项目名称', trigger: 'blur'}
  255. ],
  256. projectType: [
  257. {
  258. required: true,
  259. message: '请选择项目类型',
  260. trigger: 'change'
  261. }
  262. ],
  263. tags: [
  264. {
  265. required: true,
  266. message: '请选择项目标签',
  267. trigger: 'change'
  268. }
  269. ]
  270. },
  271. diaType: -1,
  272. parentId: 0,
  273. queryData: null
  274. }
  275. },
  276. created() {
  277. this.getTypeList()
  278. this.getNumList()
  279. this.$bus.on('serach', (res) => {
  280. if (res.dictKey === '') {
  281. this.active = 0
  282. this.onLoad(res)
  283. }
  284. })
  285. },
  286. computed: {
  287. permissionList() {
  288. return {
  289. delBtn: vaildData(this.permissions.permissions.home_del, false)
  290. }
  291. }
  292. },
  293. methods: {
  294. switchTab(item, index) {
  295. this.active = index
  296. this.onLoad({projectStage: item.dictKey})
  297. },
  298. onLoad(query = {}) {
  299. this.loading = true
  300. const data = {...query, parentId: this.parentId}
  301. this.queryData = data
  302. this.$api.project.projectList(this.page.currentPage, this.page.pageSize, data).then(res => {
  303. this.loading = false
  304. if (res.code === 200) {
  305. this.data = res.data.records.map(e => {
  306. e.projectStage = e.projectStage + ''
  307. return e
  308. })
  309. this.page.total = res.data.total
  310. }
  311. }).finally(() => {
  312. this.loading = false
  313. })
  314. },
  315. beforeOpen(done, type) {
  316. if (['edit'].includes(type)) {
  317. this.$router.push({
  318. path: '/home/details',
  319. query: {id: this.form.id, type: '0', ownerId: this.form.createUser}
  320. })
  321. } else if (type === 'view') {
  322. // this.$alert('功能建设中,尽情期待...', '消息提醒', {
  323. // confirmButtonText: 'OK'
  324. // })
  325. this.$router.push({
  326. path: '/home/pro_detail',
  327. query: {id: this.form.id}
  328. })
  329. }
  330. },
  331. currentChange(currentPage) {
  332. this.page.current = currentPage
  333. },
  334. sizeChange(pageSize) {
  335. this.page.size = pageSize
  336. },
  337. refreshChange() {
  338. this.onLoad()
  339. },
  340. treeLoad(tree, treeNode, resolve) {
  341. this.loading = true
  342. getLazyList(tree.id).then(res => {
  343. this.loading = false
  344. resolve(res.data.data.childrenList.map(e => {
  345. e.projectStage = e.projectStage.toString()
  346. return e
  347. }))
  348. })
  349. },
  350. rowDel(row) {
  351. this.$confirm('确定删除选择的项目?', {
  352. confirmButtonText: '确定',
  353. cancelButtonText: '取消',
  354. type: 'warning'
  355. })
  356. .then(() => {
  357. this.$api.project.projectRemove({ids: row.id}).then(res => {
  358. if (res.code === 200) {
  359. this.$message.success(res.msg)
  360. this.onLoad()
  361. } else {
  362. this.$message.error(res.msg)
  363. }
  364. })
  365. })
  366. },
  367. getNumList() {
  368. this.$api.project.userNunList().then(res => {
  369. if (res.code === 200) {
  370. this.numList = res.data.projectStage
  371. this.num = res.data.totalAmount
  372. }
  373. })
  374. },
  375. getTotalAmount(data) {
  376. this.$api.project.totalAmount(Object.assign(data, this.query)).then(res => {
  377. if (res.code === 200) {
  378. this.num = res.data
  379. } else {
  380. this.$message.error(res.msg)
  381. }
  382. })
  383. },
  384. getTypeList() {
  385. this.$api.project.typeList({type: 1, size: 999, current: 1}).then(res => {
  386. this.typeList = res.data.records
  387. })
  388. this.$api.common.dicList({code: 'project-tags'}).then(res => {
  389. if (res.code === 200) {
  390. this.tagsList = res.data
  391. }
  392. })
  393. },
  394. track(res) {
  395. if (res.isReport === 1) {
  396. this.$message.error('该项目已经上报')
  397. return
  398. }
  399. this.$confirm('是否确定进行项目上报', {
  400. confirmButtonText: '确定',
  401. cancelButtonText: '取消',
  402. type: 'warning'
  403. }).then(() => {
  404. const data = {id: res.id, isReport: 1}
  405. this.$api.project.proUpdate(data).then(res => {
  406. if (res.code === 200) {
  407. console.log(res)
  408. this.$message.success(res.msg)
  409. } else {
  410. this.$message.error(res.msg)
  411. }
  412. })
  413. })
  414. },
  415. projectSave() {
  416. if (this.disable) {
  417. this.$message.error('正在处理,请稍后...')
  418. return
  419. }
  420. this.$refs.form.validate((valid) => {
  421. if (valid) {
  422. this.disable = true
  423. this.addLoading = true
  424. this.$api.project.projectAdd(this.projectForm).then(res => {
  425. this.disable = false
  426. this.addLoading = false
  427. if (res.code === 200) {
  428. this.showAdd = false
  429. this.$message.success(res.msg)
  430. this.onLoad()
  431. } else {
  432. this.showAdd = false
  433. this.$message.error(res.msg)
  434. }
  435. })
  436. }
  437. })
  438. },
  439. exportExcel(res) {
  440. const data = Object.assign(this.queryData, {columnName: res})
  441. this.$api.params.exportResult(data).then(res => {
  442. const url = window.URL.createObjectURL(new Blob([res], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'}))
  443. const link = document.createElement('a')
  444. link.style.display = 'none'
  445. link.href = url
  446. const excelName = new Date().getTime() + '.xlsx'
  447. link.setAttribute('download', excelName)
  448. document.body.appendChild(link)
  449. link.click()
  450. link.remove()
  451. this.diaType = -1
  452. this.$message.success('导出成功')
  453. })
  454. }
  455. }
  456. }
  457. </script>
  458. <style lang="scss" scoped>
  459. .tip {
  460. width: 260px;
  461. height: 38px;
  462. background-color: #FBF6ED;
  463. font-weight: 500;
  464. flex-wrap: nowrap;
  465. margin-left: 20px;
  466. }
  467. .total-s {
  468. width: 200px;
  469. height: 50px;
  470. border: 1px solid #825618;
  471. border-radius: 10px;
  472. margin-right: 20px;
  473. box-shadow: 2px 2px 10px 2px rgba(113, 73, 39, 0.3);
  474. .sp {
  475. color: #ECAB56;
  476. white-space: nowrap;
  477. margin-left: 20px;
  478. }
  479. .sp1 {
  480. color: #ECAB56;
  481. margin-right: 20px;
  482. }
  483. }
  484. .total {
  485. width: 200px;
  486. height: 50px;
  487. border-radius: 10px;
  488. margin-right: 20px;
  489. background-color: #F0F2F7;
  490. .sp {
  491. color: #707070;
  492. white-space: nowrap;
  493. margin-left: 20px;
  494. }
  495. .sp1 {
  496. color: #825618;
  497. margin-right: 20px;
  498. }
  499. }
  500. .curd {
  501. :deep(.avue-crud__menu) {
  502. min-height: 10px;
  503. }
  504. }
  505. </style>