浏览代码

驾驶舱页面组件拆分,拆分后动态加载到首页

wyn 2 月之前
父节点
当前提交
6b7bb173de

+ 6 - 2
src/api/home/index.ts

@@ -1,6 +1,10 @@
 import request from '@/config/axios'
+export interface PageParam {
+  startTime?: string,
+  endTime?: string,
+}
 
 // 查询SOP列表
-export const getHomePage = async () => {
-  return await request.get({ url: '/iscs/statistics-api/getHomePage'})
+export const getHomePage = async (params: PageParam) => {
+  return await request.get({ url: '/iscs/statistics-api/getHomePage',params})
 }

+ 7 - 6
src/api/system/notify/agent/index.ts

@@ -1,10 +1,11 @@
 import request from '@/config/axios'
-
-
-
-
-
-
+export interface PageParam {
+  pageNum: number,
+  pageSize: number,
+  queryType: string, // 默认全部
+  startTime: string,
+  endTime: string,
+}
 
 export  const getMyAgent=async(params: PageParam)=>{
   return await request.get({url:'/iscs/job-ticket/getMyAgent',params})

+ 3 - 1
src/locales/zh-CN.ts

@@ -198,8 +198,10 @@ export default {
   },
   workplace: {
     welcome: '你好',
-    happyDay: '祝你开心每一天!',
+    happyDay: '祝你工作顺利!',
     toady: '今日晴',
+    todoMessage:'我的待办',
+    unreadMessage:'未读消息',
     notice: '通知公告',
     project: '项目数',
     access: '项目访问',

+ 97 - 303
src/views/Home/Index.vue

@@ -1,332 +1,126 @@
 <template>
-  <div>
-    <el-card shadow="never">
-      <el-skeleton :loading="loading" animated>
-        <el-row :gutter="16" justify="space-between">
-          <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
-            <div class="flex items-center">
-              <el-avatar :src="avatar" :size="70" class="mr-16px">
-                <img src="@/assets/imgs/avatar.gif" alt="" />
-              </el-avatar>
-              <div>
-                <div class="text-20px">
-                  {{ t('workplace.welcome') }} {{ username }} {{ t('workplace.happyDay') }}
-                </div>
-                <div class="mt-10px text-14px text-gray-500">
-                  {{ t('workplace.toady') }},20℃ - 32℃!
-                </div>
-              </div>
-            </div>
-          </el-col>
-        </el-row>
-      </el-skeleton>
-    </el-card>
-  </div>
-  <ContentWrap>
-    <div class="content">
-      <el-table :data="tableData" border style="width: 100%">
-        <el-table-column prop="ticketName" label="作业名称" min-width="600"/>
-        <el-table-column prop="workstationName" label="岗位" min-width="200" />
-        <el-table-column prop="machineryName" label="设备工艺" min-width="500" />
-        <el-table-column label="作业类型" prop="ticketType" min-width="150">
-          <template #default="scope">
-            <dict-tag :type="DICT_TYPE.TICKET_TYPE" :value="scope.row.ticketType" />
-          </template>
-        </el-table-column>
-        <el-table-column prop="ticketStartTime" label="作业开始时间" width="290" />
-      </el-table>
+  <div class="dashboard">
+    <!-- 按行渲染 -->
+    <div
+      v-for="(rowItems, rowIndex) in groupedComponents"
+      :key="rowIndex"
+      class="dashboard-row"
+    >
+      <el-card
+        v-for="item in rowItems"
+        :key="item.id"
+        class="dashboard-item"
+        shadow="hover"
+        :class="{ 'full-width': rowItems.length == 1 }"
+      >
+        <component :is="loadComponent(item.componentFilePath)" />
+      </el-card>
     </div>
-  </ContentWrap>
-
-<!--  <el-row class="mt-8px" :gutter="16" justify="space-between" style="width: 100%">-->
-<!--    <el-col :xl="16" :lg="16" :md="24" :sm="24" :xs="24" class="mb-8px" style="width: 100%">-->
-<!--      <el-card shadow="never" class="mt-8px" style="width: 100%">-->
-<!--        <el-skeleton :loading="loading" animated>-->
-          <el-row :gutter="20" justify="space-between">
-            <el-col :xl="10" :lg="20" :md="24" :sm="24" :xs="24">
-              <el-card shadow="hover" class="mb-8px">
-                <el-skeleton :loading="loading" animated>
-                  <Echart :options="pieOptionsData" :height="430" />
-                </el-skeleton>
-              </el-card>
-            </el-col>
-            <el-col :xl="14" :lg="24" :md="24" :sm="24" :xs="24">
-              <el-card shadow="hover" class="mb-8px">
-                <el-skeleton :loading="loading" animated>
-                  <Echart :options="barOptionsData" :height="430" />
-                </el-skeleton>
-              </el-card>
-            </el-col>
-<!--          </el-row>-->
-<!--        </el-skeleton>-->
-<!--      </el-card>-->
-<!--    </el-col>-->
+<!--<ChartView/>-->
 
-  </el-row>
+  </div>
 </template>
-<script lang="ts" setup>
-import { set } from 'lodash-es'
-import { EChartsOption } from 'echarts'
-import * as Home from '@/api/home/index'
-import { formatTime } from '@/utils'
-
-import { useUserStore } from '@/store/modules/user'
-// import { useWatermark } from '@/hooks/web/useWatermark'
-import type { WorkplaceTotal, Project, Notice, Shortcut } from './types'
-import { pieOptions, barOptions } from './echarts-data'
-import { useRouter } from 'vue-router'
-import {getHomePage} from "@/api/home/index";
-import {DICT_TYPE,getIntDictOptions} from "@/utils/dict";
-
-defineOptions({ name: 'Index' })
-
-const { t } = useI18n()
-const router = useRouter()
-const userStore = useUserStore()
-// const { setWatermark } = useWatermark()
-const loading = ref(true)
-const avatar = userStore.getUser.avatar
-const username = userStore.getUser.nickname
-const pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption
-const tableData=ref([])
-
 
-onMounted(()=>{
-  getJobDate()
-})
-
-const getJobDate=async()=>{
-  try{
-    const jobData=await Home.getHomePage()
-    tableData.value=jobData.jobList
-    console.log(jobData,tableData.value,'数据有什么')
-  }catch(error){}
+<script lang="ts" setup>
+import { ref, onMounted, defineAsyncComponent, computed } from "vue"
+import { getInfo } from "@/api/login"
+// import ChartView from "./chartView.vue";
+
+interface ComponentItem {
+  id: number
+  componentId: number
+  componentName: string
+  componentRow: string
+  componentColumn: string
+  componentFilePath: string
+  componentThumbnail: string
 }
 
+defineOptions({ name: "Index" })
 
-// 获取统计数
-let totalSate = reactive<WorkplaceTotal>({
-  project: 0,
-  access: 0,
-  todo: 0
-})
+const componentDetail = ref<ComponentItem[]>([])
 
-const getCount = async () => {
-  const data = {
-    project: 40,
-    access: 2340,
-    todo: 10
+// 获取 views/Home 下的所有 vue 文件
+const modules = import.meta.glob("/src/views/Home/**/*.vue")
+
+// 动态加载组件
+const loadComponent = (path: string) => {
+  const filePath = `/src/views/Home${path}.vue`
+  if (modules[filePath]) {
+    return defineAsyncComponent(modules[filePath] as any)
   }
-  totalSate = Object.assign(totalSate, data)
-}
 
-// 获取项目数
-let projects = reactive<Project[]>([])
-const getProject = async () => {
-  const data = [
-    {
-      name: 'ruoyi-vue-pro',
-      icon: 'simple-icons:springboot',
-      message: 'github.com/YunaiV/ruoyi-vue-pro',
-      personal: 'Spring Boot 单体架构',
-      time: new Date('2025-01-02'),
-      color: '#6DB33F'
-    },
-    {
-      name: 'yudao-ui-admin-vue3',
-      icon: 'ep:element-plus',
-      message: 'github.com/yudaocode/yudao-ui-admin-vue3',
-      personal: 'Vue3 + element-plus 管理后台',
-      time: new Date('2025-02-03'),
-      color: '#409EFF'
-    },
-    {
-      name: 'yudao-ui-mall-uniapp',
-      icon: 'icon-park-outline:mall-bag',
-      message: 'github.com/yudaocode/yudao-ui-mall-uniapp',
-      personal: 'Vue3 + uniapp 商城手机端',
-      time: new Date('2025-03-04'),
-      color: '#ff4d4f'
-    },
-    {
-      name: 'yudao-cloud',
-      icon: 'material-symbols:cloud-outline',
-      message: 'github.com/YunaiV/yudao-cloud',
-      personal: 'Spring Cloud 微服务架构',
-      time: new Date('2025-04-05'),
-      color: '#1890ff'
-    },
-    {
-      name: 'yudao-ui-admin-vben',
-      icon: 'devicon:antdesign',
-      message: 'github.com/yudaocode/yudao-ui-admin-vben',
-      personal: 'Vue3 + vben5(antd) 管理后台',
-      time: new Date('2025-05-06'),
-      color: '#e18525'
-    },
-    {
-      name: 'yudao-ui-admin-uniapp',
-      icon: 'ant-design:mobile',
-      message: 'github.com/yudaocode/yudao-ui-admin-uniapp',
-      personal: 'Vue3 + uniapp 管理手机端',
-      time: new Date('2025-06-01'),
-      color: '#2979ff'
-    }
-  ]
-  projects = Object.assign(projects, data)
 }
 
-// 获取通知公告
-let notice = reactive<Notice[]>([])
-const getNotice = async () => {
-  const data = [
-    {
-      title: '系统支持 JDK 8/17/21,Vue 2/3',
-      type: '技术兼容性',
-      keys: ['JDK', 'Vue'],
-      date: new Date()
-    },
-    {
-      title: '后端提供 Spring Boot 2.7/3.2 + Cloud 双架构',
-      type: '架构灵活性',
-      keys: ['Boot', 'Cloud'],
-      date: new Date()
-    },
-    {
-      title: '全部开源,个人与企业可 100% 直接使用,无需授权',
-      type: '开源免授权',
-      keys: ['无需授权'],
-      date: new Date()
-    },
-    {
-      title: '国内使用最广泛的快速开发平台,远超 10w+ 企业使用',
-      type: '广泛企业认可',
-      keys: ['最广泛', '10w+'],
-      date: new Date()
+// 去重 + 分组 + 排序
+const groupedComponents = computed(() => {
+  // 去重:根据 componentId 或 componentFilePath
+  const uniqueMap = new Map<string | number, ComponentItem>()
+  componentDetail.value.forEach((item) => {
+    if (!uniqueMap.has(item.componentId)) {
+      uniqueMap.set(item.componentId, item)
     }
-  ]
-  notice = Object.assign(notice, data)
-}
-
-// 获取快捷入口
-let shortcut = reactive<Shortcut[]>([])
+  })
+  const uniqueList = Array.from(uniqueMap.values())
 
-const getShortcut = async () => {
-  const data = [
-    {
-      name: '首页',
-      icon: 'ion:home-outline',
-      url: '/',
-      color: '#1fdaca'
-    },
-    {
-      name: '商城中心',
-      icon: 'ep:shop',
-      url: '/mall/home',
-      color: '#ff6b6b'
-    },
-    {
-      name: 'AI 大模型',
-      icon: 'tabler:ai',
-      url: '/ai/chat',
-      color: '#7c3aed'
-    },
-    {
-      name: 'ERP 系统',
-      icon: 'simple-icons:erpnext',
-      url: '/erp/home',
-      color: '#3fb27f'
-    },
-    {
-      name: 'CRM 系统',
-      icon: 'simple-icons:civicrm',
-      url: '/crm/backlog',
-      color: '#4daf1bc9'
-    },
-    {
-      name: 'IoT 物联网',
-      icon: 'fa-solid:hdd',
-      url: '/iot/home',
-      color: '#1a73e8'
+  // 按 row 分组
+  const groups: Record<string, ComponentItem[]> = {}
+  uniqueList.forEach((item) => {
+    if (!groups[item.componentRow]) {
+      groups[item.componentRow] = []
     }
-  ]
-  shortcut = Object.assign(shortcut, data)
-}
+    groups[item.componentRow].push(item)
+  })
 
-// 用户来源
-const getUserAccessSource = async () => {
-  const data = [
-    { value: 335, name: 'analysis.directAccess' },
-    { value: 310, name: 'analysis.mailMarketing' },
-    { value: 234, name: 'analysis.allianceAdvertising' },
-    { value: 135, name: 'analysis.videoAdvertising' },
-    { value: 1548, name: 'analysis.searchEngines' }
-  ]
-  set(
-    pieOptionsData,
-    'legend.data',
-    data.map((v) => t(v.name))
-  )
-  pieOptionsData!.series![0].data = data.map((v) => {
-    return {
-      name: t(v.name),
-      value: v.value
-    }
+  // 每行内部按 column 排序
+  Object.keys(groups).forEach((row) => {
+    groups[row].sort((a, b) => Number(a.componentColumn) - Number(b.componentColumn))
   })
-}
-const barOptionsData = reactive<EChartsOption>(barOptions) as EChartsOption
 
-// 周活跃量
-const getWeeklyUserActivity = async () => {
-  const data = [
-    { value: 13253, name: 'analysis.monday' },
-    { value: 34235, name: 'analysis.tuesday' },
-    { value: 26321, name: 'analysis.wednesday' },
-    { value: 12340, name: 'analysis.thursday' },
-    { value: 24643, name: 'analysis.friday' },
-    { value: 1322, name: 'analysis.saturday' },
-    { value: 1324, name: 'analysis.sunday' }
-  ]
-  set(
-    barOptionsData,
-    'xAxis.data',
-    data.map((v) => t(v.name))
-  )
-  set(barOptionsData, 'series', [
-    {
-      name: t('analysis.activeQuantity'),
-      data: data.map((v) => v.value),
-      type: 'bar'
-    }
-  ])
+  // 最终按 row 排序
+  return Object.keys(groups)
+    .sort((a, b) => Number(a) - Number(b))
+    .map((key) => groups[key])
+})
+
+// 获取数据
+const getPageContent = async () => {
+  try {
+    const pageData = await getInfo()
+    componentDetail.value = pageData.uiComponentList
+    // console.log("驾驶舱数据:", componentDetail.value)
+  } catch (error) {
+    console.log(error)
+  }
 }
 
-const getAllApi = async () => {
-  await Promise.all([
-    getCount(),
-    getProject(),
-    getNotice(),
-    getShortcut(),
-    getUserAccessSource(),
-    getWeeklyUserActivity()
-  ])
-  loading.value = false
+onMounted(() => {
+  getPageContent()
+})
+</script>
+
+
+<style lang="scss" scoped>
+.dashboard {
+  display: flex;
+  flex-direction: column;
+  gap: 15px;
+  padding: 15px;
 }
 
-const handleProjectClick = (message: string) => {
-  window.open(`https://${message}`, '_blank')
+.dashboard-row {
+  display: flex;
+  gap: 15px;
 }
 
-const handleShortcutClick = (url: string) => {
-  router.push(url)
+.dashboard-item {
+  flex: 1; /* 多个组件时自动平分 */
+  border-radius: 12px;
+  overflow: hidden;
 }
 
-getAllApi()
-</script>
-<style lang="scss">
-.content{
-  width: 100%;
-  max-height: 400px;
-  overflow: auto;
+.dashboard-item.full-width {
+  flex: none;
+  width: 100%; /* 单个组件时占满整行 */
 }
 </style>

+ 102 - 0
src/views/Home/chartView.vue

@@ -0,0 +1,102 @@
+<template>
+  <Echart :options="chartOptions" />
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted, watch } from 'vue'
+import * as Home from '@/api/home'
+import type { Ref } from 'vue'
+
+interface LoanItem {
+  day: string
+  loanCount: number
+  returnCount: number
+}
+
+const chartOptions: Ref<any> = ref({})
+
+const colors = ['#5793f3', '#d14a61'] // 蓝色表示借出,红色表示归还
+
+const setChartOptions = (data: LoanItem[]) => {
+  const days = data.map(item => item.day)
+  const loanCounts = data.map(item => item.loanCount)
+  const returnCounts = data.map(item => item.returnCount)
+
+  chartOptions.value = {
+    color: colors,
+    tooltip: {
+      trigger: 'axis',
+      axisPointer: { type: 'shadow' }
+    },
+    legend: {
+      data: ['借出数量', '归还数量']
+    },
+    grid: {
+      left: '10%',
+      right: '10%',
+      bottom: '15%'
+    },
+    xAxis: {
+      type: 'category',
+      data: days,
+      axisTick: { alignWithLabel: true },
+      axisLabel: {
+        interval: 0,       // 显示每个日期
+        rotate: 45        // 如果日期太密,可以旋转防止重叠
+      },
+      axisLine: {
+        lineStyle: {
+          color: '#5793f3' // 蓝色
+        }
+      }
+    },
+    yAxis: {
+      type: 'value',
+      min: 0,
+      max: 100,
+      name: '数量',
+      axisLine: {
+        lineStyle: {
+          color: '#5793f3' // 蓝色
+        }
+      }
+    },
+    series: [
+      {
+        name: '借出数量',
+        type: 'bar',
+        data: loanCounts
+      },
+      {
+        name: '归还数量',
+        type: 'bar',
+        data: returnCounts
+      }
+    ]
+  }
+}
+
+const fetchChartData = async () => {
+  try {
+    const now = new Date()
+    const endTime = now.toISOString()
+    const start = new Date()
+    start.setMonth(start.getMonth() - 1)
+    const startTime = start.toISOString()
+
+    const chartData = await Home.getHomePage({ startTime, endTime })
+    const loanList: LoanItem[] = chartData.loanList || []
+    console.log(loanList,'图表数据有值吗')
+    // 按日期排序,保证图表从旧到新
+    loanList.sort((a, b) => new Date(a.day).getTime() - new Date(b.day).getTime())
+
+    setChartOptions(loanList)
+  } catch (error) {
+    console.error('获取图表数据失败', error)
+  }
+}
+
+onMounted(() => {
+  fetchChartData()
+})
+</script>

+ 41 - 0
src/views/Home/doingJob.vue

@@ -0,0 +1,41 @@
+<template>
+  <div class="content">
+    <el-table :data="tableData" border style="width: 100%">
+      <el-table-column prop="ticketName" label="作业名称" min-width="600" />
+      <el-table-column prop="workstationName" label="岗位" min-width="200" />
+      <el-table-column prop="machineryName" label="设备工艺" min-width="500" />
+      <el-table-column label="作业类型" prop="ticketType" min-width="150">
+        <template #default="scope">
+          <dict-tag :type="DICT_TYPE.TICKET_TYPE" :value="scope.row.ticketType" />
+        </template>
+      </el-table-column>
+      <el-table-column prop="ticketStartTime" label="作业开始时间" width="290" />
+    </el-table>
+  </div>
+</template>
+
+<script setup lang="ts">
+import {DICT_TYPE} from "@/utils/dict";
+import * as Home from "@/api/home";
+const tableData = ref([])
+
+onMounted(() => {
+  getJobDate()
+})
+const getJobDate = async () => {
+  try {
+    const jobData = await Home.getHomePage()
+    tableData.value = jobData.jobList
+    console.log(jobData, tableData.value, '数据有什么')
+  } catch (error) {}
+}
+</script>
+
+<style scoped lang="scss">
+
+.content {
+  width: 100%;
+  max-height: 400px;
+  overflow: auto;
+}
+</style>

+ 79 - 0
src/views/Home/myTodo.vue

@@ -0,0 +1,79 @@
+<template>
+  <div class="container" @click="handleNewPageJump">
+    <section class="lefticon">
+      <img src="../../assets/images/topTodo.png" alt=""/>
+    </section>
+    <section class="righticon">
+      <p>{{ t('workplace.todoMessage') }}</p>
+      <span>{{documentTodos}}</span>
+    </section>
+  </div>
+</template>
+
+<script setup lang="ts">
+import * as Agent from '@/api/system/notify/agent/index'
+
+const router=useRouter()
+const { t } = useI18n()
+const queryParams = reactive({
+  pageNum: 1,
+  pageSize: -1,
+  queryType: '0', // 默认全部
+  startTime: '',
+  endTime: ''
+})
+const documentTodos = ref(null)
+
+
+onMounted(() => {
+  getAgentNum()
+})
+// 获取待办数量
+const getAgentNum = async () => {
+  const agentData = await Agent.getMyAgent(queryParams)
+  documentTodos.value = agentData.handleAgent.length
+  console.log(agentData.handleAgent.length, 'agentData')
+}
+
+// 代办:处理跳转逻辑
+const handleNewPageJump = () => {
+  router.push({ name: 'Agent' })
+}
+
+</script>
+
+<style scoped lang="scss">
+.container{
+  width: 320px;
+  height: 150px;
+  border: 2px solid #0b0b0b;
+  background: #ffffff;
+  border-radius: 15px;
+  display: flex;
+  .lefticon{
+    width: 50%;
+    height: 90%;
+    margin:5px 20px;
+    //background: #000;
+    img{
+      width:100%;
+      height:100%;
+    }
+  }
+  .righticon{
+    width:50%;
+    height: 100px;
+    margin:30px 15px;
+    text-align:right;
+    p{
+      font-size: 20px;
+      font-weight: bold;
+    }
+    span{
+      font-size: 30px;
+      font-weight: bold;
+      color: #cc0b0b;
+    }
+  }
+}
+</style>

+ 84 - 0
src/views/Home/unreadMessage.vue

@@ -0,0 +1,84 @@
+<template>
+  <div class="container" @click="handleNewPageJump">
+    <section class="lefticon">
+      <el-icon class="iconmessage">
+        <Message />
+      </el-icon>
+<!--      <img src="../../assets/images/topTodo.png" alt=""/>-->
+    </section>
+    <section class="righticon">
+      <p>{{ t('workplace.unreadMessage') }}</p>
+      <span>{{documentTodos}}</span>
+    </section>
+  </div>
+</template>
+
+<script setup lang="ts">
+import * as Agent from '@/api/system/notify/agent/index'
+import { Message} from '@element-plus/icons-vue'
+
+const router=useRouter()
+const { t } = useI18n()
+const queryParams = reactive({
+  pageNum: 1,
+  pageSize: -1,
+  queryType: '0', // 默认全部
+  startTime: '',
+  endTime: ''
+})
+const documentTodos = ref(0)
+
+
+onMounted(() => {
+  getAgentNum()
+})
+// 获取待办数量
+const getAgentNum = async () => {
+  const agentData = await Agent.getMyAgent(queryParams)
+  documentTodos.value = agentData.handleAgent.length
+  console.log(agentData, 'agentData')
+}
+
+// 代办:处理跳转逻辑
+const handleNewPageJump = () => {
+  router.push({ name: 'Agent' })
+}
+
+</script>
+
+<style scoped lang="scss">
+.container{
+  width: 320px;
+  height: 150px;
+  border: 2px solid #0b0b0b;
+  border-radius: 15px;
+  background: #ffffff;
+  display: flex;
+  .lefticon{
+    width: 50%;
+    height: 90%;
+    margin:5px 20px;
+    //background: #000;
+    .iconmessage{
+      font-size: 130px;
+    }
+  }
+  .righticon{
+    width:70%;
+    height: 164px;
+    margin:30px 15px;
+    padding: 10px 0;
+    //background: #ede4e4;
+    text-align:right;
+    p{
+      font-size: 20px;
+      font-weight: bold;
+    }
+    span{
+      font-size: 30px;
+      font-weight: bold;
+      color: #cc0b0b;
+    }
+  }
+}
+</style>

+ 50 - 0
src/views/Home/welcomeBar.vue

@@ -0,0 +1,50 @@
+<template>
+<!--  <div>呼呼呼呼</div>-->
+  <div class="flex items-center">
+    <el-avatar :src="avatar" :size="70" class="mr-16px">
+      <img src="@/assets/imgs/avatar.gif" alt="" />
+    </el-avatar>
+    <div>
+      <div class="text-20px">
+        {{ t('workplace.welcome') }} {{ username }} {{ t('workplace.happyDay') }}
+      </div>
+      <div class="mt-10px text-14px text-gray-500">
+        {{ todayStr }}
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import {useUserStore} from "@/store/modules/user";
+import { ref } from "vue"
+
+const { t } = useI18n()
+const userStore = useUserStore()
+const avatar = userStore.getUser.avatar
+const username = userStore.getUser.nickname
+
+
+// 星期映射
+const weekDays = ["星期日","星期一","星期二","星期三","星期四","星期五","星期六"]
+
+// 获取当前日期
+const getToday = () => {
+  const now = new Date()
+  const year = now.getFullYear()
+  const month = now.getMonth() + 1
+  const day = now.getDate()
+  const week = weekDays[now.getDay()]
+  return `${year}年${month}月${day}日,${week}`
+}
+
+const todayStr = ref(getToday())
+</script>
+
+
+<style scoped lang="scss">
+.items-center{
+  background: #fff;
+  padding: 20px;
+}
+</style>