ZaiZai 1 vuosi sitten
vanhempi
commit
5d9e5579af

+ 7 - 6
src/styles/view/datav.scss

@@ -37,14 +37,15 @@
         }
         .hc-datav-search-select {
             position: absolute;
-            justify-content: end;
-            padding-right: 14px;
-            bottom: 10px;
+            align-items: center;
+            padding: 0 14px;
+            bottom: 0;
+            .date {
+                text-align: right;
+                font-size: 14px;
+            }
         }
     }
-    .hc-datav-total {
-        margin-top: -10px;
-    }
     .hc-datav-divider {
         position: relative;
         margin-top: 8px;

+ 70 - 13
src/views/home/datav.vue

@@ -13,11 +13,14 @@
                 <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="searchForm.quarter" :datas="quarterArr" />
-                        <HcDatavSelect v-model="searchForm.level" :datas="levelArr" />
-                        <HcDatavSelect v-model="searchForm.stage" :datas="stageArr" />
-                        <HcDatavSelect v-model="searchForm.type" :datas="typeArr" />
+                        <HcDatavSelect v-model="pageType" :datas="pageTypeArr" :clearable="false" @change="pageTypeChange" />
+                        <HcDatavSelect v-model="searchForm.month" :datas="monthArr" placeholder="选择月份" />
+                        <HcDatavSelect v-model="searchForm.lag" :datas="lagArr" />
+                        <HcDatavSelect v-model="searchForm.level" :datas="levelArr" placeholder="滞后等级" />
+                        <HcDatavSelect v-model="searchForm.stage" :datas="stageArr" placeholder="项目阶段" />
+                        <HcDatavSelect v-model="searchForm.type" :datas="typeArr" placeholder="项目类型" />
                     </div>
+                    <div class="date flex-1">截止时间:2024年04月08日</div>
                 </div>
             </div>
             <div class="hc-datav-total relative p-[14px]">
@@ -29,10 +32,15 @@
                         <HcDatavCard title="计划总投资额" num="1590" unit="亿" color="#EEB500" />
                     </el-col>
                     <el-col :span="6">
-                        <HcDatavCard title="目前实际完成投资额" num="590" unit="亿" color="#0DD70C" />
+                        <HcDatavCard num="590" unit="亿" color="#0DD70C">
+                            <template #title>
+                                <span style="color: #FE0301;">目前</span>
+                                <span>实际完成投资额</span>
+                            </template>
+                        </HcDatavCard>
                     </el-col>
                     <el-col :span="6">
-                        <HcDatavCard title="未完成投资额" num="1000" unit="亿" color="#FF0000" />
+                        <HcDatavCard title="投资完成比例" num="58" unit="%" color="#1DC98B" />
                     </el-col>
                 </el-row>
             </div>
@@ -110,7 +118,17 @@
                         </div>
                         <div class="hc-datav-divider" />
                         <div class="hc-datav-table relative">
-                            <HcDatavTable1 :datas="tableData1" />
+                            <HcDatavTable :column="tableColumn1" :datas="tableData1" is-current @row-click="tableRowClick">
+                                <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>
@@ -132,7 +150,7 @@
                         </div>
                     </div>
                     <div class="hc-datav-row-line relative">
-                        <div class="title">项目进度趋势</div>
+                        <div class="title">项目数据</div>
                         <div class="hc-full relative">
                             <HcDatavCharts />
                         </div>
@@ -204,7 +222,17 @@
                         </div>
                         <div class="hc-datav-divider" />
                         <div class="hc-datav-table relative">
-                            <HcDatavTable2 :datas="tableData2" />
+                            <HcDatavTable :column="tableColumn2" :datas="tableData2">
+                                <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>
@@ -226,8 +254,7 @@ 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 HcDatavTable1 from './modules/table1.vue'
-import HcDatavTable2 from './modules/table2.vue'
+import HcDatavTable from './modules/table.vue'
 import HcDatavCharts from './modules/charts.vue'
 import { isNullES } from 'js-fast-way'
 
@@ -250,6 +277,13 @@ onMounted(() => {
     setTimeout(() => {
         onWindowResize()
     }, 100)
+
+    //生成月份
+    let newMonthArr = [{ id: 0, name: '所有' }]
+    for (let i = 0; i < 12; i++) {
+        newMonthArr.push({ id: i + 1, name: `${i + 1}月` })
+    }
+    monthArr.value = newMonthArr
 })
 
 //关闭引导提示
@@ -259,14 +293,27 @@ const tourFinishClose = () => {
 }
 
 //搜索表单
-const searchForm = ref({ year: '2024', quarter: '1', level: '0', stage: '1', type: '1' })
+const pageType = ref('1')
+const searchForm = ref({ year: '2024', month: 0, level: '0', stage: '1', type: '1' })
 const yearArr = [{ id: '2024', name: '2024年' }, { id: '2023', name: '2023年' }, { id: '2022', name: '2022年' }]
-const quarterArr = [{ id: '1', name: '一季度' }, { id: '2', name: '二季度' }, { id: '3', name: '三季度' }, { id: '4', name: '四季度' }, { id: '0', name: '所有' }]
+const pageTypeArr = [{ id: '1', name: '项目数据看板' }, { id: '2', name: '工作要点' }]
+const monthArr = ref([])
+const lagArr = [{ id: '1', name: '超进度项目' }, { id: '2', name: '常规项目' }, { id: '3', name: '滞后项目' }, { id: '0', name: '所有' }]
 const levelArr = [{ id: '1', name: '一级' }, { id: '2', name: '二级' }, { id: '3', name: '三级' }, { id: '0', name: '所有' }]
 const stageArr = [{ id: '1', name: '项目阶段' }, { id: '2', name: '在建项目' }, { id: '3', name: '新开工项目' }, { id: '4', name: '建成项目' }]
 const typeArr = [{ id: '1', name: '公路' }, { id: '2', name: '水利' }, { id: '3', name: '房建' }, { id: '4', name: '铁路' }]
 
+//页面类型改变
+const pageTypeChange = () => {
+
+}
+
 //表格1
+const tableColumn1 = [
+    { key: 'key1', name: '项目阶段' }, { key: 'key2', name: '项目类型' },
+    { key: 'key3', name: '计划总投资' }, { key: 'key4', name: '实际已投资' },
+    { key: 'key5', name: '未完成投资' },
+]
 const tableData1 = ref([
     { key1: '在建项目', key2: '铁路', key3: '12000', key4: '12000', key5: 2000 },
     { key1: '在建项目', key2: '民航', key3: '12000', key4: '12000', key5: 2000 },
@@ -285,7 +332,17 @@ const tableData1 = ref([
     { key1: '在建项目', key2: 'xx', key3: '12000', key4: '12000', key5: 2000 },
 ])
 
+//表格被点击
+const tableRowClick = (row) => {
+    console.log(row)
+}
+
 //表格2
+const tableColumn2 = [
+    { key: 'key1', name: '项目阶段' }, { key: 'key2', name: '项目类型' },
+    { key: 'key3', name: '项目数' }, { key: 'key4', name: '已完成项目数' },
+    { key: 'key5', name: '未完成项目数' },
+]
 const tableData2 = ref([
     { key1: '在建项目', key2: '铁路', key3: '12', key4: '12', key5: 12, key6: 12 },
     { key1: '在建项目', key2: '民航', key3: '12', key4: '12', key5: 12, key6: 12 },

+ 19 - 5
src/views/home/modules/card.vue

@@ -7,16 +7,25 @@
             <div class="angle a4 absolute bottom-0 right-0 h-[21px] w-[34px]" />
         </div>
         <div class="card-content relative h-full">
-            <div class="title text-[28px] font-bold">{{ title }}</div>
-            <div class="quantity absolute bottom-[-8px] right-[4px] font-bold" :style="{ color }">
-                <span class="num vertical-sub text-[60px]">{{ num }}</span>
-                <span v-if="unit" class="unit ml-[5px] text-[28px]">({{ unit }})</span>
-            </div>
+            <template v-if="isSlotDefault">
+                <slot />
+            </template>
+            <template v-else>
+                <div v-if="isSlotTitle" class="title text-[28px] font-bold">
+                    <slot name="title" />
+                </div>
+                <div v-else class="title text-[28px] font-bold">{{ title }}</div>
+                <div class="quantity absolute bottom-[-8px] right-[4px] font-bold" :style="{ color }">
+                    <span class="num vertical-sub text-[60px]">{{ num }}</span>
+                    <span v-if="unit" class="unit ml-[5px] text-[28px]">({{ unit }})</span>
+                </div>
+            </template>
         </div>
     </div>
 </template>
 
 <script setup>
+import { ref, useSlots } from 'vue'
 defineProps({
     title: {
         type: String,
@@ -35,6 +44,11 @@ defineProps({
         default: '',
     },
 })
+
+//判断<slot>是否有传值
+const slots = useSlots()
+const isSlotDefault = ref(!!slots.default)
+const isSlotTitle = ref(!!slots.title)
 </script>
 
 <style scoped lang="scss">

+ 109 - 0
src/views/home/modules/table.vue

@@ -0,0 +1,109 @@
+<template>
+    <div class="hc-datav-table-main hc-full">
+        <el-table
+            ref="tableRef" class="top-table tablebox" :data="tableData" border :row-key="rowKey" :highlight-current-row="isCurrent"
+            @mouseover="clearScroll" @mouseleave="createScroll" @row-click="rowClick"
+        >
+            <template v-for="item in tableColumn" :key="item.key">
+                <el-table-column :align="item.align ?? 'center'" :label="item.name" :prop="item.key" :width="item.width">
+                    <template v-if="item.isSlot" #default="scope">
+                        <slot :index="scope.$index" :name="item.key" :row="scope.row" />
+                    </template>
+                </el-table-column>
+            </template>
+        </el-table>
+    </div>
+</template>
+
+<script setup>
+import { onMounted, onUnmounted, ref, useSlots, watch } from 'vue'
+import { getRandom, isNullES } from 'js-fast-way'
+
+//参数
+const props = defineProps({
+    column: {
+        type: Array,
+        default: () => ([]),
+    },
+    datas: {
+        type: Array,
+        default: () => ([]),
+    },
+    rowKey: {
+        type: String,
+        default: 'id',
+    },
+    isCurrent: {
+        type: Boolean,
+        default: false,
+    },
+})
+
+//事件
+const emit = defineEmits(['rowClick'])
+
+//表格表头
+const tableColumn = ref(props.column)
+watch(() => props.column, (data) => {
+    tableColumn.value = data
+    setIsSlots()
+}, { deep: true })
+
+//表格数据
+const tableData = ref(props.datas)
+watch(() => props.datas, (data) => {
+    tableData.value = data
+}, { deep: true })
+
+//判断<slot>是否有传值
+const slots = useSlots()
+
+const setIsSlots = async () => {
+    await getSlotKey(tableColumn.value)
+}
+
+const getSlotKey = async (arr) => {
+    for (let i = 0; i < arr.length; i++) {
+        if (isNullES(arr[i].key)) {
+            arr[i].key = getRandom()
+        }
+        arr[i].isSlot = !!slots[arr[i].key]
+    }
+}
+
+let timer = null
+const tableRef = ref(null)
+
+const clearScroll = () => {
+    clearInterval(timer)
+    timer = null
+}
+const createScroll = () => {
+    clearScroll()
+    // 拿到 table
+    const table = tableRef.value.layout.table.refs
+    // 拿到可以滚动的元素
+    const wrapper = table.bodyWrapper.firstElementChild.firstElementChild
+
+    timer = setInterval(() => {
+        wrapper.scrollTop += 1
+        // 判断是否滚动到底部,如果到底部了置为0(可视高度 + 距离顶部 = 整个高度)
+        if (wrapper.clientHeight + wrapper.scrollTop === wrapper.scrollHeight) {
+            wrapper.scrollTop = 0
+        }
+    }, 50)
+}
+
+//表格行被点击
+const rowClick = (row, column, event) => {
+    emit('rowClick', row, column, event)
+}
+
+onMounted(() => {
+    setIsSlots()
+    createScroll()
+})
+onUnmounted(() => {
+    clearScroll()
+})
+</script>

+ 0 - 71
src/views/home/modules/table1.vue

@@ -1,71 +0,0 @@
-<template>
-    <div class="hc-datav-table-main hc-full">
-        <el-table ref="tableRef" class="top-table tablebox" :data="tableData" border @mouseover="clearScroll" @mouseleave="createScroll">
-            <el-table-column prop="key1" label="项目阶段" align="center" />
-            <el-table-column prop="key2" label="项目类型" align="center" />
-            <el-table-column prop="key3" label="计划总投资" align="center">
-                <template #default="scope">
-                    <span style="color: #06A3FF;" class="font-bold">{{ scope.row.key3 }}</span>
-                </template>
-            </el-table-column>
-            <el-table-column prop="key4" label="实际已投资" align="center">
-                <template #default="scope">
-                    <span style="color: #10C90F;" class="font-bold">{{ scope.row.key4 }}</span>
-                </template>
-            </el-table-column>
-            <el-table-column prop="key5" label="未完成投资" align="center">
-                <template #default="scope">
-                    <span style="color: #D7A70D;" class="font-bold">{{ scope.row.key5 }}</span>
-                </template>
-            </el-table-column>
-        </el-table>
-    </div>
-</template>
-
-<script setup>
-import { onMounted, onUnmounted, ref, watch } from 'vue'
-
-//参数
-const props = defineProps({
-    datas: {
-        type: Array,
-        default: () => ([]),
-    },
-})
-
-//监听
-const tableData = ref(props.datas)
-watch(() => props.datas, (val) => {
-    tableData.value = val
-}, { deep: true })
-
-let timer = null
-const tableRef = ref(null)
-
-const clearScroll = () => {
-    clearInterval(timer)
-    timer = null
-}
-const createScroll = () => {
-    clearScroll()
-    // 拿到 table
-    const table = tableRef.value.layout.table.refs
-    // 拿到可以滚动的元素
-    const wrapper = table.bodyWrapper.firstElementChild.firstElementChild
-
-    timer = setInterval(() => {
-        wrapper.scrollTop += 1
-        // 判断是否滚动到底部,如果到底部了置为0(可视高度 + 距离顶部 = 整个高度)
-        if (wrapper.clientHeight + wrapper.scrollTop === wrapper.scrollHeight) {
-            wrapper.scrollTop = 0
-        }
-    }, 50)
-}
-
-onMounted(() => {
-    createScroll()
-})
-onUnmounted(() => {
-    clearScroll()
-})
-</script>

+ 0 - 77
src/views/home/modules/table2.vue

@@ -1,77 +0,0 @@
-<template>
-    <div class="hc-datav-table-main hc-full">
-        <el-table ref="tableRef" class="top-table tablebox" :data="tableData" border @mouseover="clearScroll" @mouseleave="createScroll">
-            <el-table-column prop="key1" label="项目阶段" align="center" />
-            <el-table-column prop="key2" label="项目类型" align="center" />
-            <el-table-column prop="key3" label="计划项目" align="center">
-                <template #default="scope">
-                    <span style="color: #FF0606;" class="font-bold">{{ scope.row.key3 }}</span>
-                </template>
-            </el-table-column>
-            <el-table-column prop="key4" label="未制定计划项目" align="center">
-                <template #default="scope">
-                    <span style="color: #D7A70D;" class="font-bold">{{ scope.row.key4 }}</span>
-                </template>
-            </el-table-column>
-            <el-table-column prop="key5" label="按计划完成项目" align="center">
-                <template #default="scope">
-                    <span style="color: #06A3FF;" class="font-bold">{{ scope.row.key5 }}</span>
-                </template>
-            </el-table-column>
-            <el-table-column prop="key6" label="未按计划完成项目" align="center">
-                <template #default="scope">
-                    <span style="color: #10C90F;" class="font-bold">{{ scope.row.key6 }}</span>
-                </template>
-            </el-table-column>
-        </el-table>
-    </div>
-</template>
-
-<script setup>
-import { onMounted, onUnmounted, ref, watch } from 'vue'
-
-//参数
-const props = defineProps({
-    datas: {
-        type: Array,
-        default: () => ([]),
-    },
-})
-
-//监听
-const tableData = ref(props.datas)
-watch(() => props.datas, (val) => {
-    tableData.value = val
-}, { deep: true })
-
-
-let timer = null
-const tableRef = ref(null)
-
-const clearScroll = () => {
-    clearInterval(timer)
-    timer = null
-}
-const createScroll = () => {
-    clearScroll()
-    // 拿到 table
-    const table = tableRef.value.layout.table.refs
-    // 拿到可以滚动的元素
-    const wrapper = table.bodyWrapper.firstElementChild.firstElementChild
-
-    timer = setInterval(() => {
-        wrapper.scrollTop += 1
-        // 判断是否滚动到底部,如果到底部了置为0(可视高度 + 距离顶部 = 整个高度)
-        if (wrapper.clientHeight + wrapper.scrollTop === wrapper.scrollHeight) {
-            wrapper.scrollTop = 0
-        }
-    }, 50)
-}
-
-onMounted(() => {
-    createScroll()
-})
-onUnmounted(() => {
-    clearScroll()
-})
-</script>