123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590 |
- <template>
- <div class="hc-datav-main hc-full">
- <img class="hc-datav-bg" :src="bgPng" alt="bg">
- <div id="hc-datav-header-body" class="relative">
- <div class="hc-datav-header">
- <img id="datav-header-bg" :src="png2" alt="头部图">
- <div class="header-title hc-flex-center w-full">
- <div ref="nameRef" class="name hc-flex" @click="toHomePage">
- <i class="i-solar-graph-outline" />
- 项目数据看板
- </div>
- </div>
- <div class="hc-datav-search-select hc-flex w-full">
- <div ref="searchRef" class="relative">
- <HcDatavSelect v-model="searchForm.year" :datas="yearArr" />
- <HcDatavSelect v-model="pageType" :datas="pageTypeArr" :clearable="false" @change="pageTypeChange" />
- <template v-if="pageType === '1'">
- <HcDatavSelect v-model="searchForm.month" :datas="monthArr" placeholder="选择月份" @change="searchChange" />
- <HcDatavSelect v-model="searchForm.projectScheduleType" :datas="lagArr" @change="searchChange" />
- <HcDatavSelect v-if="searchForm.projectScheduleType === '3'" v-model="searchForm.projectScheduleGrade" :datas="levelArr" placeholder="滞后等级" @change="searchChange" />
- </template>
- <HcDatavSelect v-model="searchForm.projectStage" :datas="stageArr" placeholder="项目阶段" @change="searchChange" />
- <HcDatavSelect v-if="pageType === '1'" v-model="searchForm.projectType" :datas="typeArr" placeholder="项目类型" @change="searchChange" />
- <HcDatavSelect v-else v-model="searchForm.quarter" :datas="quarterArr" placeholder="选择季度" />
- </div>
- <div class="date flex-1">截止时间:2024年04月08日</div>
- </div>
- </div>
- <div class="hc-datav-total relative p-[14px]">
- <el-row v-if="pageType === '1'" :gutter="24">
- <el-col :span="6">
- <HcDatavCard title="项目总量" :num="projectStat.projectTotal" unit="" color="#D5DEFF" />
- </el-col>
- <el-col :span="6">
- <HcDatavCard title="计划总投资额" :num="projectStat.planAllMoney" unit="亿" color="#EEB500" />
- </el-col>
- <el-col :span="6">
- <HcDatavCard :num="projectStat.currentMoney" unit="亿" color="#0DD70C">
- <template #title>
- <span style="color: #FE0301;">目前</span>
- <span>实际完成投资额</span>
- </template>
- </HcDatavCard>
- </el-col>
- <el-col :span="6">
- <HcDatavCard title="投资完成比例" :num="projectStat.investRatio" unit="%" color="#1DC98B" />
- </el-col>
- </el-row>
- <el-row v-else :gutter="24">
- <el-col :span="6" />
- <el-col :span="6">
- <HcDatavCard>
- <div class="hc-diy-datav-card hc-full hc-flex-center">
- <span class="num vertical-sub text-[60px] font-bold" style="color: #ECCF6D">8</span>
- <span class="text text-[28px] font-bold">个方面</span>
- </div>
- </HcDatavCard>
- </el-col>
- <el-col :span="6">
- <HcDatavCard>
- <div class="hc-diy-datav-card hc-full hc-flex-center">
- <span class="num vertical-sub text-[60px] font-bold" style="color: #0BD70E">30</span>
- <span class="text text-[28px] font-bold">项任务</span>
- </div>
- </HcDatavCard>
- </el-col>
- <el-col :span="6" />
- </el-row>
- </div>
- <div class="hc-datav-divider" />
- </div>
- <div id="hc-datav-row-total-body" class="hc-datav-row-total relative p-[14px]">
- <el-row v-if="pageType === '1'" :gutter="24" class="h-full">
- <el-col :span="8" class="h-full">
- <div class="hc-datav-row-column h-full">
- <div class="title">投资数据</div>
- <div class="notes">
- <span>(已完成/</span>
- <span class="red">未完成</span>
- <span>)</span>
- </div>
- <div class="gird-card-box relative mt-4">
- <hc-row :gutter="20">
- <hc-col :span="12">
- <div class="gird-card hc-flex p-[14px]">
- <div class="upper-num a1 hc-flex-center h-[52px] w-[52px] text-[30px]">Ⅰ</div>
- <div class="content relative ml-[12px] h-[52px] flex-1">
- <div class="name mb-[10px] text-center text-[16px]">一季度</div>
- <div class="data text-center text-[24px]">
- <span class="num font-bold">{{ investStat?.oneFinished || 0 }}</span>
- <span class="line">/</span>
- <span class="red font-bold">{{ investStat?.oneUnFinished || 0 }}</span>
- <span class="unit ml-[5px] text-[14px]">(亿)</span>
- </div>
- </div>
- </div>
- </hc-col>
- <hc-col :span="12">
- <div class="gird-card hc-flex p-[14px]">
- <div class="upper-num a2 hc-flex-center h-[52px] w-[52px] text-[30px]">Ⅱ</div>
- <div class="content relative ml-[12px] h-[52px] flex-1">
- <div class="name mb-[10px] text-center text-[16px]">二季度</div>
- <div class="data text-center text-[24px]">
- <span class="num font-bold">{{ investStat?.twoFinished || 0 }}</span>
- <span class="line">/</span>
- <span class="red font-bold">{{ investStat?.twoUnFinished || 0 }}</span>
- <span class="unit ml-[5px] text-[14px]">(亿)</span>
- </div>
- </div>
- </div>
- </hc-col>
- <hc-col :span="12">
- <div class="gird-card hc-flex p-[14px]">
- <div class="upper-num a3 hc-flex-center h-[52px] w-[52px] text-[30px]">Ⅲ</div>
- <div class="content relative ml-[12px] h-[52px] flex-1">
- <div class="name mb-[10px] text-center text-[16px]">三季度</div>
- <div class="data text-center text-[24px]">
- <span class="num font-bold">{{ investStat?.threeFinished || 0 }}</span>
- <span class="line">/</span>
- <span class="red font-bold">{{ investStat?.threeUnFinished || 0 }}</span>
- <span class="unit ml-[5px] text-[14px]">(亿)</span>
- </div>
- </div>
- </div>
- </hc-col>
- <hc-col :span="12">
- <div class="gird-card hc-flex p-[14px]">
- <div class="upper-num a4 hc-flex-center h-[52px] w-[52px] text-[30px]">Ⅳ</div>
- <div class="content relative ml-[12px] h-[52px] flex-1">
- <div class="name mb-[10px] text-center text-[16px]">四季度</div>
- <div class="data text-center text-[24px]">
- <span class="num font-bold">{{ investStat?.fourFinished || 0 }}</span>
- <span class="line">/</span>
- <span class="red font-bold">{{ investStat?.fourUnFinished || 0 }}</span>
- <span class="unit ml-[5px] text-[14px]">(亿)</span>
- </div>
- </div>
- </div>
- </hc-col>
- </hc-row>
- </div>
- <div class="hc-datav-divider" />
- <div v-if="searchForm.projectScheduleType !== '3'" class="hc-datav-table relative">
- <HcDatavTable :column="tableColumn1" :datas="tableData1" is-current @row-click="tableRowClick">
- <template #planAllMoney="{ row }">
- <span style="color: #06A3FF;" class="font-bold">{{ row.planAllMoney }}</span>
- </template>
- <template #currentMoney="{ row }">
- <span style="color: #10C90F;" class="font-bold">{{ row.currentMoney }}</span>
- </template>
- <template #unFinishedMoney="{ row }">
- <span style="color: #D7A70D;" class="font-bold">{{ row.unFinishedMoney }}</span>
- </template>
- </HcDatavTable>
- </div>
- <div v-else class="hc-datav-table relative">
- <HcDatavTable :column="lagColumn1" :datas="lagData1" is-current @row-click="lagRowClick">
- <template #key3="{ row }">
- <span style="color: #06A3FF;" class="font-bold">{{ row.key3 }}</span>
- </template>
- <template #key4="{ row }">
- <span style="color: #10C90F;" class="font-bold">{{ row.key4 }}</span>
- </template>
- <template #key5="{ row }">
- <span style="color: #D7A70D;" class="font-bold">{{ row.key5 }}</span>
- </template>
- </HcDatavTable>
- </div>
- </div>
- </el-col>
- <el-col :span="8" class="h-full">
- <div class="hc-datav-row-charts relative text-center">
- <div class="row-charts relative inline-block h-[335px] w-[520px]">
- <div class="title-box a1">
- <span>常规项目</span>
- <span class="num">{{ projectStat.total1 }}</span>
- </div>
- <div class="title-box a2">
- <span>超进度项目</span>
- <span class="num">{{ projectStat.total2 }}</span>
- </div>
- <div class="title-box a3">
- <span>滞后项目</span>
- <span class="num">{{ projectStat.total3 }}</span>
- </div>
- </div>
- </div>
- <div class="hc-datav-row-line relative">
- <div class="title">项目数据</div>
- <div class="hc-full relative">
- <HcDatavCharts v-if="isDatavCharts" />
- </div>
- </div>
- </el-col>
- <el-col :span="8" class="h-full">
- <div class="hc-datav-row-column h-full">
- <div class="title">进度数据</div>
- <div class="notes">
- <span>(已完成/</span>
- <span class="red">未完成</span>
- <span>)</span>
- </div>
- <div class="gird-card-box relative mt-4">
- <hc-row :gutter="20">
- <hc-col :span="12">
- <div class="gird-card hc-flex p-[14px]">
- <div class="upper-num a1 hc-flex-center h-[52px] w-[52px] text-[30px]">Ⅰ</div>
- <div class="content relative ml-[12px] h-[52px] flex-1">
- <div class="name mb-[10px] text-center text-[16px]">一季度</div>
- <div class="data text-center text-[24px]">
- <span class="num font-bold">{{ scheduleStat?.oneFinished || 0 }}</span>
- <span class="line">/</span>
- <span class="red font-bold">{{ scheduleStat?.oneUnFinished || 0 }}</span>
- </div>
- </div>
- </div>
- </hc-col>
- <hc-col :span="12">
- <div class="gird-card hc-flex p-[14px]">
- <div class="upper-num a2 hc-flex-center h-[52px] w-[52px] text-[30px]">Ⅱ</div>
- <div class="content relative ml-[12px] h-[52px] flex-1">
- <div class="name mb-[10px] text-center text-[16px]">二季度</div>
- <div class="data text-center text-[24px]">
- <span class="num font-bold">{{ scheduleStat?.twoFinished || 0 }}</span>
- <span class="line">/</span>
- <span class="red font-bold">{{ scheduleStat?.twoUnFinished || 0 }}</span>
- </div>
- </div>
- </div>
- </hc-col>
- <hc-col :span="12">
- <div class="gird-card hc-flex p-[14px]">
- <div class="upper-num a3 hc-flex-center h-[52px] w-[52px] text-[30px]">Ⅲ</div>
- <div class="content relative ml-[12px] h-[52px] flex-1">
- <div class="name mb-[10px] text-center text-[16px]">三季度</div>
- <div class="data text-center text-[24px]">
- <span class="num font-bold">{{ scheduleStat?.threeFinished || 0 }}</span>
- <span class="line">/</span>
- <span class="red font-bold">{{ scheduleStat?.threeUnFinished || 0 }}</span>
- </div>
- </div>
- </div>
- </hc-col>
- <hc-col :span="12">
- <div class="gird-card hc-flex p-[14px]">
- <div class="upper-num a4 hc-flex-center h-[52px] w-[52px] text-[30px]">Ⅳ</div>
- <div class="content relative ml-[12px] h-[52px] flex-1">
- <div class="name mb-[10px] text-center text-[16px]">四季度</div>
- <div class="data text-center text-[24px]">
- <span class="num font-bold">{{ scheduleStat?.fourFinished || 0 }}</span>
- <span class="line">/</span>
- <span class="red font-bold">{{ scheduleStat?.fourUnFinished || 0 }}</span>
- </div>
- </div>
- </div>
- </hc-col>
- </hc-row>
- </div>
- <div class="hc-datav-divider" />
- <div v-if="searchForm.projectScheduleType !== '3'" class="hc-datav-table relative">
- <HcDatavTable :column="tableColumn2" :datas="tableData2">
- <template #projectTotal="{ row }">
- <span style="color: #D8A70F;" class="font-bold">{{ row.projectTotal }}</span>
- </template>
- <template #finishedTotal="{ row }">
- <span style="color: #0BD70E;" class="font-bold">{{ row.finishedTotal }}</span>
- </template>
- <template #unFinishedTotal="{ row }">
- <span style="color: #FF0000;" class="font-bold">{{ row.unFinishedTotal }}</span>
- </template>
- </HcDatavTable>
- </div>
- <div v-else class="hc-datav-table relative">
- <HcDatavTable :column="lagColumn2" :datas="lagData2">
- <template #key3="{ row }">
- <span style="color: #D8A70F;" class="font-bold">{{ row.key3 }}</span>
- </template>
- <template #key4="{ row }">
- <span style="color: #0BD70E;" class="font-bold">{{ row.key4 }}</span>
- </template>
- <template #key5="{ row }">
- <span style="color: #FF0000;" class="font-bold">{{ row.key5 }}</span>
- </template>
- </HcDatavTable>
- </div>
- </div>
- </el-col>
- </el-row>
- <div v-else class="hc-datav-row-column work h-full">
- <div class="title">工作要点</div>
- <div class="hc-datav-table relative" style="height: 100%;">
- <HcDatavTable :column="workColumn" :datas="workData" />
- </div>
- </div>
- </div>
- <el-tour v-model="tourOpen" @close="tourFinishClose">
- <el-tour-step :target="nameRef" title="操作提示" description="点击这里,进入数据分析工具" />
- <el-tour-step :target="searchRef" title="操作提示" description="这里进行数据筛选查询" />
- </el-tour>
- </div>
- </template>
- <script setup>
- import { onMounted, onUnmounted, ref } from 'vue'
- import router from '~src/router/index'
- import { useAppStore } from '~src/store'
- import { getStore, setStore } from 'hc-vue3-ui'
- import bgPng from '~src/assets/images/datav-bg.png'
- import png2 from '~src/assets/images/datav-2.png'
- import HcDatavSelect from './modules/select.vue'
- import HcDatavCard from './modules/card.vue'
- import HcDatavTable from './modules/table.vue'
- import HcDatavCharts from './modules/charts.vue'
- import { getArrValue, getObjValue, isNullES } from 'js-fast-way'
- import { getDictionaryData } from '~src/utils/tools'
- import projectApi from '~api/datav/projectdata'
- const store = useAppStore()
- //引导
- const nameRef = ref(null)
- const searchRef = ref(null)
- const tourOpen = ref(false)
- onMounted(() => {
- const isTourOpen = getStore('isTourOpen')
- if (isNullES(isTourOpen)) {
- setTimeout(() => {
- tourOpen.value = true
- }, 500)
- }
- //窗口大小改变
- windowResize()
- setTimeout(() => {
- onWindowResize()
- }, 100)
- //生成月份
- let newMonthArr = [{ id: -1, name: '所有' }]
- for (let i = 0; i < 12; i++) {
- newMonthArr.push({ id: i + 1, name: `${i + 1}月` })
- }
- monthArr.value = newMonthArr
- getProType()
- getProStation()
- searchChange()
- })
- //关闭引导提示
- const tourFinishClose = () => {
- console.log('关闭引导提示')
- setStore('isTourOpen', true)
- }
- //搜索表单
- const pageType = ref('1')
- const searchForm = ref({ year: '2024', month: -1, projectScheduleGrade: '-1', projectStage: null, projectType: null, projectScheduleType:'-1' })
- const yearArr = [{ id: '2024', name: '2024年' }, { id: '2023', name: '2023年' }, { id: '2022', name: '2022年' }]
- const pageTypeArr = [{ id: '1', name: '项目数据看板' }, { id: '2', name: '工作要点' }]
- const monthArr = ref([])
- const lagArr = [{ id: '1', name: '超进度项目' }, { id: '2', name: '常规项目' }, { id: '3', name: '滞后项目' }, { id: '-1', name: '所有' }]
- const levelArr = [{ id: '1', name: '一级' }, { id: '2', name: '二级' }, { id: '3', name: '三级' }, { id: '-1', name: '所有' }]
- const stageArr = ref([])
- const typeArr = ref([])
- const quarterArr = [{ id: '1', name: '一季度' }, { id: '2', name: '二季度' }, { id: '3', name: '三季度' }, { id: '4', name: '四季度' }]
- const getProType = async () => {
- let data = await getDictionaryData('projectType', true)
- data.forEach((ele)=>{
- typeArr.value.push({
- id:ele.value,
- name:ele.label,
- })
- })
- }
- const getProStation = async () => {
- let data = await getDictionaryData('projectStage', true)
- data.forEach((ele)=>{
- stageArr.value.push({
- id:ele.value,
- name:ele.label,
- })
- })
- }
- //项目
- //搜索条
- //页面类型改变
- const pageTypeChange = () => {
- }
- //搜索条件改变1
- const searchChange = ()=>{
- getDataProjectStat()
- getDataInvestStat()
- getScheduleStat()
- }
- //获取项目统计
- const projectStat = ref({
- projectTotal:0,
- planAllMoney:0,
- currentMoney:0,
- investRatio:0,
- total1:0,
- total2:0,
- total3:0,
- })
- //获取项目统计
- const getDataProjectStat = async ()=>{
- const { error, code, data } = await projectApi.dataProjectStat(searchForm.value)
- //处理数据
- if (!error && code === 200) {
- projectStat.value = getObjValue(data)
- } else {
- projectStat.value = {
- projectTotal:0,
- planAllMoney:0,
- currentMoney:0,
- investRatio:0,
- total1:0,
- total2:0,
- total3:0,
- }
- }
- }
- //获取投资数据
- const investStat = ref({
- oneFinished:0,
- oneUnFinished:0,
- twoFinished:0,
- twoUnFinished:0,
- threeFinished:0,
- threeUnFinished:0,
- fourFinished:0,
- fourUnFinished:0,
- })
- const getDataInvestStat = async ()=>{
- const { error, code, data } = await projectApi.dataInvestStat(searchForm.value)
- //处理数据
- if (!error && code === 200) {
- investStat.value = getObjValue(data)
- tableData1.value = getArrValue(data['list'])
- } else {
- investStat.value = {
- oneFinished:0,
- oneUnFinished:0,
- twoFinished:0,
- twoUnFinished:0,
- threeFinished:0,
- threeUnFinished:0,
- fourFinished:0,
- fourUnFinished:0,
- }
- tableData1.value = []
- }
- }
- //获取进度数据
- const scheduleStat = ref({
- oneFinished:0,
- oneUnFinished:0,
- twoFinished:0,
- twoUnFinished:0,
- threeFinished:0,
- threeUnFinished:0,
- fourFinished:0,
- fourUnFinished:0,
- })
- const getScheduleStat = async ()=>{
- const { error, code, data } = await projectApi.schedulestStat(searchForm.value)
- //处理数据
- if (!error && code === 200) {
- scheduleStat.value = getObjValue(data)
- tableData2.value = getArrValue(data['list'])
- } else {
- scheduleStat.value = {
- oneFinished:0,
- oneUnFinished:0,
- twoFinished:0,
- twoUnFinished:0,
- threeFinished:0,
- threeUnFinished:0,
- fourFinished:0,
- fourUnFinished:0,
- }
- tableData2.value = []
- }
- }
- //表格1
- const tableColumn1 = [
- { key: 'projectStageName', name: '项目阶段' }, { key: 'projectTypeName', name: '项目类型' },
- { key: 'planAllMoney', name: '计划总投资' }, { key: 'currentMoney', name: '实际已投资' },
- { key: 'unFinishedMoney', name: '未完成投资' },
- ]
- const tableData1 = ref([])
- //表格被点击
- const isDatavCharts = ref(true)
- const tableRowClick = (row) => {
- console.log(row)
- //模拟改变图表
- isDatavCharts.value = false
- setTimeout(() => {
- isDatavCharts.value = true
- }, 100)
- }
- //滞后表格1
- const lagColumn1 = [
- { key: 'key1', name: '滞后等级' }, { key: 'key2', name: '项目名称' },
- { key: 'key3', name: '计划总投资' }, { key: 'key4', name: '实际已投资' },
- { key: 'key5', name: '未完成投资' },
- ]
- const lagData1 = ref([
- { key1: '一级', key2: 'xx', key3: '12000', key4: '12000', key5: 2000 },
- { key1: '二级', key2: 'xx', key3: '12000', key4: '12000', key5: 2000 },
- { key1: '三级', key2: 'xx', key3: '12000', key4: '12000', key5: 2000 },
- ])
- const lagRowClick = (row) => {
- console.log(row)
- //模拟改变图表
- isDatavCharts.value = false
- setTimeout(() => {
- isDatavCharts.value = true
- }, 100)
- }
- //表格2
- const tableColumn2 = [
- { key: 'projectStageName', name: '项目阶段' }, { key: 'projectTypeName', name: '项目类型' },
- { key: 'projectTotal', name: '项目数' }, { key: 'finishedTotal', name: '已完成项目数' },
- { key: 'unFinishedTotal', name: '未完成项目数' },
- ]
- const tableData2 = ref([])
- //滞后表格2
- const lagColumn2 = [
- { key: 'key1', name: '滞后等级' }, { key: 'key2', name: '项目名称' },
- { key: 'key3', name: '进度滞后季度' }, { key: 'key4', name: '进度滞后月份' },
- { key: 'key5', name: '进度百分比' },
- ]
- const lagData2 = ref([
- { key1: '一级', key2: 'xx', key3: '一季度', key4: '1月', key5: '38%' },
- { key1: '二级', key2: 'xx', key3: '二季度', key4: '2月', key5: '48%' },
- { key1: '三级', key2: 'xx', key3: '三季度', key4: '3月', key5: '58%' },
- ])
- //工作要点表格
- const workColumn = [
- { key: 'key1', name: '项目阶段' }, { key: 'key2', name: '目标任务' },
- { key: 'key3', name: '工作内容' }, { key: 'key4', name: '1月' },
- { key: 'key5', name: '2月' }, { key: 'key6', name: '3月' },
- { key: 'key7', name: '责任单位' },
- ]
- const workData = ref([
- { key1: 'xxxx', key2: 'xxxx', key3: 'xxxx', key4: 'xxxx', key5: 'xxxx', key6: 'xxxx', key7: 'xxxx' },
- { key1: 'xxxx', key2: 'xxxx', key3: 'xxxx', key4: 'xxxx', key5: 'xxxx', key6: 'xxxx', key7: 'xxxx' },
- { key1: 'xxxx', key2: 'xxxx', key3: 'xxxx', key4: 'xxxx', key5: 'xxxx', key6: 'xxxx', key7: 'xxxx' },
- ])
- //跳转到首页
- const toHomePage = () => {
- router.push({ name: store.page })
- }
- //监听浏览器窗口变化
- const windowResize = () => {
- window.addEventListener('resize', resizeEvent)
- }
- const resizeEvent = () => {
- window.requestAnimationFrame(() => {
- onWindowResize()
- })
- }
- //设置尺寸
- const onWindowResize = () => {
- const height = document.getElementById('hc-datav-header-body').offsetHeight
- document.getElementById('hc-datav-row-total-body').style.height = `calc(100% - ${height + 10}px)`
- }
- //被卸载
- onUnmounted(() => {
- window.removeEventListener('resize', resizeEvent)
- })
- </script>
- <style lang="scss">
- @import '~src/styles/view/datav';
- </style>
|