admin.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  1. <template>
  2. <el-scrollbar class="hc-main-scrollbar hc-home-main">
  3. <div class="hc-main-row">
  4. <el-row :gutter="14">
  5. <el-col :span="4">
  6. <HcCardItem ui="hac-card-item">
  7. <template #header>
  8. <div class="hac-card-title g">
  9. 年度合同指标
  10. </div>
  11. </template>
  12. <template #extra>
  13. <img class="hac-extra-img" :src="QImg" alt="">
  14. </template>
  15. <div class="hac-card-item-body">
  16. <div class="money">
  17. ¥{{ planAnnualTarget.annualContractTarget }}
  18. </div>
  19. <div class="text">
  20. 已收入:¥{{ planAnnualTarget.yearReturned }}
  21. </div>
  22. </div>
  23. </HcCardItem>
  24. </el-col>
  25. <el-col :span="4">
  26. <HcCardItem ui="hac-card-item">
  27. <template #header>
  28. <div class="hac-card-title g">
  29. 年度利润指标
  30. </div>
  31. </template>
  32. <template #extra>
  33. <img class="hac-extra-img" :src="QImg" alt="">
  34. </template>
  35. <div class="hac-card-item-body">
  36. <div class="money">
  37. ¥{{ planAnnualTarget.annualProfitTarget }}
  38. </div>
  39. <div class="text">
  40. 已盈利:¥{{ planAnnualTarget.yearProfit }}
  41. </div>
  42. </div>
  43. </HcCardItem>
  44. </el-col>
  45. <el-col :span="16">
  46. <HcCardItem ui="hac-card-item">
  47. <template #header>
  48. <div class="hac-card-title g">
  49. 进度统计
  50. </div>
  51. </template>
  52. <div class="hac-card-item-body">
  53. <div class="hac-item-progress">
  54. <div class="title">
  55. 年度合同指标
  56. </div>
  57. <div class="num">
  58. <el-progress :text-inside="true" :stroke-width="18" :percentage="planAnnualTarget.contractSchedule" color="#8978FD" />
  59. </div>
  60. </div>
  61. <div class="hac-item-progress">
  62. <div class="title">
  63. 年度利润指标
  64. </div>
  65. <div class="num">
  66. <el-progress :text-inside="true" :stroke-width="18" :percentage="planAnnualTarget.profitSchedule" color="#73A3FE" />
  67. </div>
  68. </div>
  69. </div>
  70. </HcCardItem>
  71. </el-col>
  72. </el-row>
  73. <HcCardItem ui="hac-card-item mt-4">
  74. <template #header>
  75. <div class="hac-card-title text-black">
  76. 年度各项费用统计
  77. </div>
  78. </template>
  79. <template #extra>
  80. <HcDropdown v-if="yearData.length > 0" :cur="planYear1" :datas="yearData" :all="yearData.length > 0" @change="planYear1Change" />
  81. </template>
  82. <div class="hac-card-item-body mb-2">
  83. <el-row :gutter="14">
  84. <el-col :span="6">
  85. <HcGradientCard color="purple1">
  86. <div class="hc-card-item-sub">
  87. <div class="item-sub-content">
  88. <div class="title">
  89. 总合同
  90. </div>
  91. <div class="num-box">
  92. <span class="num">{{ annualCostData.yearContractMoney ?? 0 }}</span>
  93. <span class="text">元</span>
  94. </div>
  95. </div>
  96. <div class="item-sub-icon">
  97. <img class="img" :src="HeImg" alt="">
  98. </div>
  99. </div>
  100. </HcGradientCard>
  101. </el-col>
  102. <el-col :span="6">
  103. <HcGradientCard color="blue1">
  104. <div class="hc-card-item-sub">
  105. <div class="item-sub-content">
  106. <div class="title">
  107. 总收入
  108. </div>
  109. <div class="num-box">
  110. <span class="num">{{ annualCostData.yearReturned ?? 0 }}</span>
  111. <span class="text">元</span>
  112. </div>
  113. </div>
  114. <div class="item-sub-icon">
  115. <img class="img" :src="ShouImg" alt="">
  116. </div>
  117. </div>
  118. </HcGradientCard>
  119. </el-col>
  120. <el-col :span="6">
  121. <HcGradientCard color="red1">
  122. <div class="hc-card-item-sub">
  123. <div class="item-sub-content">
  124. <div class="title">
  125. 总实际支出
  126. </div>
  127. <div class="num-box">
  128. <span class="num">{{ annualCostData.yearStaffDisburse ?? 0 }}</span>
  129. <span class="text">元</span>
  130. </div>
  131. </div>
  132. <div class="item-sub-icon">
  133. <img class="img" :src="ZhiImg" alt="">
  134. </div>
  135. </div>
  136. </HcGradientCard>
  137. </el-col>
  138. <el-col :span="6">
  139. <HcGradientCard color="purple1">
  140. <div class="hc-card-item-sub">
  141. <div class="item-sub-content">
  142. <div class="title">
  143. 总计划支出
  144. </div>
  145. <div class="num-box">
  146. <span class="num">{{ annualCostData.totalBudget ?? 0 }}</span>
  147. <span class="text">元</span>
  148. </div>
  149. </div>
  150. <div class="item-sub-icon">
  151. <img class="img" :src="Zhi1Img" alt="">
  152. </div>
  153. </div>
  154. </HcGradientCard>
  155. </el-col>
  156. </el-row>
  157. </div>
  158. </HcCardItem>
  159. <HcCardItem ui="hac-card-item mt-4">
  160. <template #header>
  161. <div class="hac-card-title text-black">
  162. 年度各项目支出对比
  163. </div>
  164. </template>
  165. <template #extra>
  166. <HcDropdown v-if="yearData.length > 0" :cur="planYear2" :datas="yearData" @change="planYear2Change" />
  167. </template>
  168. <div class="hc-row-echarts-box" style="height: 260px">
  169. <BarLabelRotation v-if="expendDatas.length > 0" is-month :datas="expendDatas" />
  170. <HcNoData v-else />
  171. </div>
  172. </HcCardItem>
  173. <el-row :gutter="14" class="mt-4">
  174. <el-col :span="10">
  175. <HcCardItem ui="hac-card-item">
  176. <template #header>
  177. <div class="hac-card-title text-black">
  178. 当月各部门计划安排比重
  179. </div>
  180. </template>
  181. <template #extra>
  182. <el-date-picker v-model="planTime" type="month" format="YYYY-MM" value-format="YYYY-MM" style="width: 130px;" @change="planTimeChange" />
  183. </template>
  184. <div class="hac-card-item-body" style="height: 410px">
  185. <HcTable ui="no-border" :is-index="false" :column="tableColumn" :datas="tableData" />
  186. </div>
  187. </HcCardItem>
  188. </el-col>
  189. <el-col :span="14">
  190. <div class="hac-card-col-item">
  191. <HcCardItem ui="hac-card-item">
  192. <template #header>
  193. <div class="hac-card-icon-title">
  194. <HcIcon name="alarm-warning" ui="text-orange text-xl" />
  195. <el-badge :value="tableData1.length">
  196. <span class="ml-2 mr-3 text-black">影响回款的风险计划</span>
  197. </el-badge>
  198. </div>
  199. </template>
  200. <div class="hac-card-item-body" style="height: 160px">
  201. <HcTable ui="no-border" :is-index="false" :column="tableColumn1" :datas="tableData1">
  202. <template #action="{ row }">
  203. <el-button plain size="small" type="primary" @click="rowViewClick(row)">
  204. 查看
  205. </el-button>
  206. </template>
  207. </HcTable>
  208. </div>
  209. </HcCardItem>
  210. </div>
  211. <div class="hac-card-col-item mt-4">
  212. <el-row :gutter="14">
  213. <el-col :span="12">
  214. <HcCardItem ui="hac-card-item">
  215. <template #header>
  216. <div class="hac-card-title text-black">
  217. 各项目支出占比统计
  218. </div>
  219. </template>
  220. <template #extra>
  221. <HcDropdown v-if="yearData.length > 0" :cur="planYear3" :datas="yearData" @change="planYear3Change" />
  222. </template>
  223. <div class="hac-card-item-body" style="height: 160px">
  224. <BorderRadius v-if="expendStatisticsDatas.length > 0" :datas="expendStatisticsDatas" />
  225. <HcStatus v-else class="border-radius-status" />
  226. </div>
  227. </HcCardItem>
  228. </el-col>
  229. <el-col :span="12">
  230. <HcCardItem ui="hac-card-item">
  231. <template #header>
  232. <div class="hac-card-title text-black">
  233. 各项目收入占比统计
  234. </div>
  235. </template>
  236. <template #extra>
  237. <HcDropdown v-if="yearData.length > 0" :cur="planYear4" :datas="yearData" @change="planYear4Change" />
  238. </template>
  239. <div class="hac-card-item-body" style="height: 160px">
  240. <SimpleChart v-if="incomeStatisticsDatas.length > 0" :datas="incomeStatisticsDatas" />
  241. <HcStatus v-else class="simple-chart-status" />
  242. </div>
  243. </HcCardItem>
  244. </el-col>
  245. </el-row>
  246. </div>
  247. </el-col>
  248. </el-row>
  249. <HcCardItem ui="hac-card-item mt-4">
  250. <template #header>
  251. <div class="hac-card-title text-black">
  252. 项目服务阶段进程
  253. </div>
  254. </template>
  255. <template #extra>
  256. <el-select v-if="projectData.length > 0" v-model="portalProjectId" @change="portalProjectIdChange">
  257. <el-option v-for="items in projectData" :key="items.projectId" :label="items.projectName" :value="items.projectId" />
  258. </el-select>
  259. </template>
  260. <div class="hc-row-echarts-box pt-5 mb-1">
  261. <template v-for="(item, index) in projectProcessData" v-if="projectProcessData.length > 0">
  262. <ProgressChart
  263. :left-title="index === 0 ? '计划执行进度' : ''"
  264. :right-title="index === 0 ? '已支出成本' : ''"
  265. :title="item.processName"
  266. :left-ratio="item.processProgressBar"
  267. :right-ratio="item.processCostProgressBar"
  268. :right-text="item.processCostCount"
  269. />
  270. </template>
  271. <HcStatus v-else class="project-process-status" />
  272. </div>
  273. </HcCardItem>
  274. </div>
  275. </el-scrollbar>
  276. </template>
  277. <script setup>
  278. import { onActivated, onMounted, ref } from 'vue'
  279. import { useRouter } from 'vue-router'
  280. import QImg from '~src/assets/images/q.png'
  281. import HeImg from '~src/assets/images/he.png'
  282. import ShouImg from '~src/assets/images/shou.png'
  283. import ZhiImg from '~src/assets/images/zhi.png'
  284. import Zhi1Img from '~src/assets/images/zhi1.png'
  285. import BarLabelRotation from '~com/echarts/BarLabelRotation.vue'
  286. import BorderRadius from '~com/echarts/BorderRadius.vue'
  287. import SimpleChart from '~com/echarts/SimpleChart.vue'
  288. import ProgressChart from '~com/echarts/ProgressChart.vue'
  289. import mainApi from '~api/home/index'
  290. import { getProjectList } from '~api/other'
  291. //时间类
  292. import dayjs from 'dayjs'
  293. import 'dayjs/locale/zh-cn'
  294. import { getArrValue, getObjValue } from 'js-fast-way'
  295. dayjs.locale('zh-cn')
  296. //初始组合式
  297. const router = useRouter()
  298. //年份
  299. const planYear = dayjs().format('YYYY') + '年'
  300. const planDate = dayjs().format('YYYY-MM')
  301. //页面首次渲染完成时
  302. onMounted(async () => {
  303. await getYearList()
  304. getYearDataApi()
  305. })
  306. //缓存页面被激活时
  307. onActivated(() => {
  308. getPlanAnnualTarget()
  309. getYearDataApi()
  310. getTableData1()
  311. getTableData()
  312. getProjectData()
  313. })
  314. const getYearDataApi = () => {
  315. if (yearData.value.length > 0) {
  316. getPortalAnnualCost()
  317. getExpendDatas()
  318. getExpendStatisticsData()
  319. getIncomeStatisticsData()
  320. }
  321. }
  322. //项目类型
  323. const planAnnualTarget = ref({})
  324. const getPlanAnnualTarget = async () => {
  325. const { error, code, data } = await mainApi.portalAnnualTarget()
  326. //判断状态
  327. if (!error && code === 200) {
  328. planAnnualTarget.value = getObjValue(data)
  329. } else {
  330. planAnnualTarget.value = {}
  331. }
  332. }
  333. //获取年度列表
  334. const yearData = ref([])
  335. const getYearList = async () => {
  336. const { error, code, data } = await mainApi.yearList()
  337. //判断状态
  338. if (!error && code === 200) {
  339. const arr = getArrValue(data)
  340. //判断当前年份是否在列表中
  341. if (arr.indexOf(planYear) > -1) {
  342. planYear1.value = planYear
  343. } else {
  344. planYear1.value = arr[0]
  345. }
  346. yearData.value = arr
  347. } else {
  348. yearData.value = []
  349. planYear1.value = ''
  350. annualCostData.value = {
  351. yearContractMoney: 0,
  352. yearReturned: 0,
  353. yearStaffDisburse: 0,
  354. totalBudget: 0,
  355. }
  356. }
  357. }
  358. //年度各项费用统计
  359. const planYear1 = ref(planYear)
  360. const planYear1Change = (val) => {
  361. planYear1.value = val
  362. getPortalAnnualCost()
  363. }
  364. //获取数据
  365. const annualCostData = ref({
  366. yearContractMoney: 0, yearReturned: 0, yearStaffDisburse: 0, totalBudget: 0,
  367. })
  368. const getPortalAnnualCost = async () => {
  369. const { error, code, data } = await mainApi.portalAnnualCost({
  370. year: planYear1.value,
  371. })
  372. //判断状态
  373. if (!error && code === 200) {
  374. annualCostData.value = getObjValue(data)
  375. } else {
  376. annualCostData.value = {
  377. yearContractMoney: 0,
  378. yearReturned: 0,
  379. yearStaffDisburse: 0,
  380. totalBudget: 0,
  381. }
  382. }
  383. }
  384. //年度各项目支出对比
  385. const planYear2 = ref(planYear)
  386. const planYear2Change = (val) => {
  387. planYear2.value = val
  388. getExpendDatas()
  389. }
  390. //年度各项目支出对比
  391. const expendDatas = ref([])
  392. const getExpendDatas = async () => {
  393. expendDatas.value = []
  394. const { error, code, data } = await mainApi.portalAnnualProjectCost({
  395. year: planYear2.value,
  396. })
  397. //判断状态
  398. if (!error && code === 200) {
  399. expendDatas.value = getArrValue(data)
  400. } else {
  401. expendDatas.value = []
  402. }
  403. }
  404. //当月各部门计划安排比重
  405. const planTime = ref(planDate)
  406. const planTimeChange = () => {
  407. getTableData()
  408. }
  409. const tableColumn = [
  410. { key: 'projectName', name: '项目名称' },
  411. { key: 'businessRatio', name: '实施投入', align: 'center' },
  412. { key: 'devRatio', name: '研发投入', align: 'center' },
  413. { key: 'maintainRatio', name: '维护投入', align: 'center' },
  414. ]
  415. const tableData = ref([])
  416. const getTableData = async () => {
  417. tableData.value = []
  418. const { error, code, data } = await mainApi.portalDeptMonthPlanRatio({
  419. date: planTime.value,
  420. })
  421. //判断状态
  422. if (!error && code === 200) {
  423. tableData.value = getArrValue(data)
  424. } else {
  425. tableData.value = []
  426. }
  427. }
  428. //影响回款的风险计划
  429. const tableColumn1 = [
  430. { key: 'projectName', name: '项目名称' },
  431. { key: 'costTypeValue', name: '风险部门', align: 'center' },
  432. { key: 'timeOutPlanTotal', name: '延期计划条数', align: 'center' },
  433. { key: 'action', name: '操作', align: 'center' },
  434. ]
  435. const tableData1 = ref([])
  436. const getTableData1 = async () => {
  437. tableData1.value = []
  438. const { error, code, data } = await mainApi.portalRiskPlan()
  439. //判断状态
  440. if (!error && code === 200) {
  441. tableData1.value = getArrValue(data)
  442. } else {
  443. tableData1.value = []
  444. }
  445. }
  446. //查看
  447. const rowViewClick = (row) => {
  448. router.push({ name: 'program-section' })
  449. }
  450. //各项目支出占比统计
  451. const planYear3 = ref(planYear)
  452. const planYear3Change = (val) => {
  453. planYear3.value = val
  454. getExpendStatisticsData()
  455. }
  456. const expendStatisticsDatas = ref([])
  457. const getExpendStatisticsData = async () => {
  458. expendStatisticsDatas.value = []
  459. const { error, code, data } = await mainApi.portalProjectCostRatio(planYear3.value)
  460. //判断状态
  461. if (!error && code === 200) {
  462. const arr = getArrValue(data)
  463. arr.forEach(item => {
  464. item.name = item.projectName
  465. item.value = item.projectCost
  466. })
  467. expendStatisticsDatas.value = arr
  468. } else {
  469. expendStatisticsDatas.value = []
  470. }
  471. }
  472. //各项目收入占比统计
  473. const planYear4 = ref(planYear)
  474. const planYear4Change = (val) => {
  475. planYear4.value = val
  476. getIncomeStatisticsData()
  477. }
  478. const incomeStatisticsDatas = ref([
  479. { value: 1048, name: '奉建路' },
  480. { value: 735, name: '西环线' },
  481. { value: 580, name: '陈油路' },
  482. { value: 484, name: '宝北路' },
  483. ])
  484. const getIncomeStatisticsData = async () => {
  485. incomeStatisticsDatas.value = []
  486. const { error, code, data } = await mainApi.portalProjectIncomeRatio(planYear4.value)
  487. //判断状态
  488. if (!error && code === 200) {
  489. const arr = getArrValue(data)
  490. arr.forEach(item => {
  491. item.name = item.projectName
  492. item.value = item.projectIncome
  493. })
  494. incomeStatisticsDatas.value = arr
  495. } else {
  496. incomeStatisticsDatas.value = []
  497. }
  498. }
  499. //获取项目数据
  500. const portalProjectId = ref('')
  501. const projectData = ref([])
  502. const getProjectData = async () => {
  503. const { error, code, data } = await getProjectList()
  504. //判断状态
  505. if (!error && code === 200) {
  506. const arr = getArrValue(data)
  507. portalProjectId.value = arr.length > 0 ? arr[0].projectId : ''
  508. projectData.value = arr
  509. getPortalProjectProcess().then()
  510. } else {
  511. portalProjectId.value = ''
  512. projectData.value = []
  513. projectProcessData.value = []
  514. }
  515. }
  516. const portalProjectIdChange = () => {
  517. getPortalProjectProcess()
  518. }
  519. //获取数据
  520. const projectProcessData = ref([])
  521. const getPortalProjectProcess = async () => {
  522. projectProcessData.value = []
  523. const { error, code, data } = await mainApi.portalProjectProcess(portalProjectId.value)
  524. //判断状态
  525. if (!error && code === 200) {
  526. projectProcessData.value = getArrValue(data)
  527. } else {
  528. projectProcessData.value = []
  529. }
  530. }
  531. </script>
  532. <style lang="scss" scoped>
  533. @import "~src/styles/home/admin.scss";
  534. </style>
  535. <style lang="scss">
  536. .hac-item-progress .num .el-progress .el-progress-bar .el-progress-bar__outer,
  537. .hac-item-progress .num .el-progress .el-progress-bar .el-progress-bar__inner {
  538. border-radius: 3px;
  539. }
  540. .hc-home-main .hc-row-echarts-box .hc-no-data-box .no-data-c {
  541. position: relative;
  542. width: 200px;
  543. top: -15px;
  544. }
  545. .hc-home-main .hac-card-col-item .hac-card-item {
  546. .border-radius-status, .simple-chart-status {
  547. .page-status {
  548. top: -10px;
  549. .page-status-img {
  550. width: 160px;
  551. }
  552. .page-status-text {
  553. font-size: 14px;
  554. margin-top: -10px;
  555. }
  556. }
  557. }
  558. }
  559. .hc-home-main .hac-card-item .hc-row-echarts-box .project-process-status {
  560. .page-status {
  561. top: -15px;
  562. margin-bottom: 14px;
  563. .page-status-text {
  564. font-size: 16px;
  565. }
  566. }
  567. }
  568. </style>