Browse Source

Merge branch 'main' into refactor/theme

xiaoxian521 3 years ago
parent
commit
6b151eae1b

+ 20 - 0
.vscode/vue3.2.setup-snippets

@@ -0,0 +1,20 @@
+{
+  "Vue3.2快速生成模板": {
+    "prefix": "Vue3.2",
+    "body": [
+      "<!-- $1 -->",
+      "<script setup lang='ts'>",
+      "\t$2",
+      "</script>\n",
+      "<template>",
+      "\t<div>",
+      "\t\t$3",
+      "\t</div>",
+      "</template>\n",
+      "<style scoped>",
+      "\t$4",
+      "</style>"
+    ],
+    "description": "Vue3.2"
+  }
+}

+ 1 - 0
package.json

@@ -23,6 +23,7 @@
     "@logicflow/core": "^0.7.1",
     "@logicflow/extension": "^0.7.1",
     "@vueuse/core": "^6.7.1",
+    "@vueuse/motion": "^2.0.0-beta.4",
     "animate.css": "^4.1.1",
     "await-to-js": "^3.0.0",
     "axios": "^0.21.1",

BIN
src/assets/401.gif


+ 0 - 0
src/assets/green.png → src/assets/car.png


BIN
src/assets/login.png


+ 1 - 0
src/assets/svg/back_top.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M2.88 18.054a35.897 35.897 0 0 1 8.531-16.32.8.8 0 0 1 1.178 0c.166.18.304.332.413.455a35.897 35.897 0 0 1 8.118 15.865c-2.141.451-4.34.747-6.584.874l-2.089 4.178a.5.5 0 0 1-.894 0l-2.089-4.178a44.019 44.019 0 0 1-6.584-.874zm6.698-1.123l1.157.066L12 19.527l1.265-2.53 1.157-.066a42.137 42.137 0 0 0 4.227-.454A33.913 33.913 0 0 0 12 4.09a33.913 33.913 0 0 0-6.649 12.387c1.395.222 2.805.374 4.227.454zM12 15a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-2a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>

+ 1 - 1
src/components/ReCharts/src/Infinite.vue

@@ -111,7 +111,7 @@ let classOption = reactive({
 
   .warp {
     width: 95%;
-    height: 230px;
+    height: 215px;
     margin: 0 auto;
     overflow: hidden;
 

+ 9 - 5
src/components/ReMap/src/Amap.vue

@@ -3,7 +3,7 @@ import AMapLoader from "@amap/amap-jsapi-loader";
 import { reactive, getCurrentInstance, onBeforeMount, onUnmounted } from "vue";
 import { mapJson } from "/@/api/mock";
 import { deviceDetection } from "/@/utils/deviceDetection";
-import greenCar from "/@/assets/green.png";
+import car from "/@/assets/car.png";
 
 export interface MapConfigureInter {
   on: Fn;
@@ -15,6 +15,10 @@ export interface MapConfigureInter {
   plugin?: Fn;
 }
 
+type resultType = {
+  info: Array<undefined>;
+};
+
 export interface mapInter {
   loading: boolean;
 }
@@ -24,7 +28,7 @@ let map: MapConfigureInter;
 
 const instance = getCurrentInstance();
 
-const mapSet: mapInter = reactive({
+const mapSet = reactive({
   loading: deviceDetection() ? false : true
 });
 
@@ -72,7 +76,7 @@ onBeforeMount(() => {
             var { driver, plateNumber, orientation } = data[0];
             var content = `<img style="transform: scale(1) rotate(${
               360 - Number(orientation)
-            }deg);" src='${greenCar}' />`;
+            }deg);" src='${car}' />`;
             marker.setContent(content);
             marker.setLabel({
               direction: "bottom",
@@ -92,7 +96,7 @@ onBeforeMount(() => {
 
       // 获取模拟车辆信息
       mapJson()
-        .then(res => {
+        .then((res: resultType) => {
           let points: object = res.info.map((v: any) => {
             return {
               lnglat: [v.lng, v.lat],
@@ -134,7 +138,7 @@ onUnmounted(() => {
 
 <style lang="scss" scoped>
 #mapview {
-  height: 100vh;
+  height: calc(100vh - 86px);
 }
 
 :deep(.amap-marker-label) {

+ 30 - 5
src/layout/components/appMain.vue

@@ -8,6 +8,7 @@ import {
   getCurrentInstance
 } from "vue";
 import { RouterView } from "vue-router";
+import backTop from "/@/assets/svg/back_top.svg";
 import { usePermissionStoreHook } from "/@/store/modules/permission";
 
 const props = defineProps({
@@ -65,15 +66,26 @@ const transitionMain = defineComponent({
     <router-view>
       <template #default="{ Component, route }">
         <el-scrollbar v-if="props.fixedHeader">
-          <el-backtop target=".app-main .el-scrollbar__wrap"></el-backtop>
+          <el-backtop title="回到顶部" target=".app-main .el-scrollbar__wrap">
+            <backTop />
+          </el-backtop>
           <transitionMain :route="route">
             <keep-alive
               v-if="keepAlive"
               :include="usePermissionStoreHook().cachePageList"
             >
-              <component :is="Component" :key="route.fullPath" />
+              <component
+                :is="Component"
+                :key="route.fullPath"
+                class="main-content"
+              />
             </keep-alive>
-            <component v-else :is="Component" :key="route.fullPath" />
+            <component
+              v-else
+              :is="Component"
+              :key="route.fullPath"
+              class="main-content"
+            />
           </transitionMain>
         </el-scrollbar>
         <div v-else>
@@ -82,9 +94,18 @@ const transitionMain = defineComponent({
               v-if="keepAlive"
               :include="usePermissionStoreHook().cachePageList"
             >
-              <component :is="Component" :key="route.fullPath" />
+              <component
+                :is="Component"
+                :key="route.fullPath"
+                class="main-content"
+              />
             </keep-alive>
-            <component v-else :is="Component" :key="route.fullPath" />
+            <component
+              v-else
+              :is="Component"
+              :key="route.fullPath"
+              class="main-content"
+            />
           </transitionMain>
         </div>
       </template>
@@ -105,4 +126,8 @@ const transitionMain = defineComponent({
   min-height: 100vh;
   position: relative;
 }
+
+.main-content {
+  margin: 24px;
+}
 </style>

+ 3 - 18
src/layout/components/panel/index.vue

@@ -1,33 +1,18 @@
 <script setup lang="ts">
 import { ref } from "vue";
-import { useEventListener, onClickOutside } from "@vueuse/core";
+import { onClickOutside } from "@vueuse/core";
 import { emitter } from "/@/utils/mitt";
 
 let show = ref<Boolean>(false);
 const target = ref(null);
-onClickOutside(target, () => {
+onClickOutside(target, event => {
+  if (event.clientX > target.value.offsetLeft) return;
   show.value = false;
 });
 
-const addEventClick = (): void => {
-  useEventListener("click", closeSidebar);
-};
-
-const closeSidebar = (evt: any): void => {
-  const parent = evt.target.closest(".right-panel");
-  if (!parent) {
-    show.value = false;
-    window.removeEventListener("click", closeSidebar);
-  }
-};
-
 emitter.on("openPanel", () => {
   show.value = true;
 });
-
-defineExpose({
-  addEventClick
-});
 </script>
 
 <template>

+ 5 - 1
src/layout/components/sidebar/hamBurger.vue

@@ -17,7 +17,11 @@ const toggleClick = () => {
 </script>
 
 <template>
-  <div :class="classes.container" @click="toggleClick">
+  <div
+    :class="classes.container"
+    :title="props.isActive ? '点击折叠' : '点击展开'"
+    @click="toggleClick"
+  >
     <svg
       :class="['hamburger', props.isActive ? 'is-active' : '']"
       viewBox="0 0 1024 1024"

+ 69 - 5
src/layout/components/sidebar/sidebarItem.vue

@@ -1,8 +1,13 @@
 <script setup lang="ts">
 import path from "path";
-import { PropType, ref } from "vue";
+import { storageLocal } from "/@/utils/storage";
+import { PropType, ref, nextTick } from "vue";
 import { childrenType } from "../../types";
 import Icon from "/@/components/ReIcon/src/Icon.vue";
+const layout = ref(
+  storageLocal.getItem("responsive-layout") || "vertical-dark"
+);
+const menuMode = layout.value.layout.split("-")[0] === "vertical";
 
 const props = defineProps({
   item: {
@@ -19,6 +24,28 @@ const props = defineProps({
 });
 
 const onlyOneChild: childrenType = ref(null);
+// 存放菜单是否存在showTooltip属性标识
+const hoverMenuMap = new WeakMap();
+// 存储菜单文本dom元素
+const menuTextRef = ref(null);
+
+function hoverMenu(key) {
+  // 如果当前菜单showTooltip属性已存在,退出计算
+  if (hoverMenuMap.get(key)) return;
+
+  nextTick(() => {
+    // 如果文本内容的整体宽度大于其可视宽度,则文本溢出
+    menuTextRef.value?.scrollWidth > menuTextRef.value?.clientWidth
+      ? Object.assign(key, {
+          showTooltip: true
+        })
+      : Object.assign(key, {
+          showTooltip: false
+        });
+
+    hoverMenuMap.set(key, true);
+  });
+}
 
 function hasOneShowingChild(
   children: childrenType[] = [],
@@ -65,8 +92,23 @@ function resolvePath(routePath) {
         ></component>
       </el-icon>
       <template #title>
-        <div style="display: flex; align-items: center">
-          <span>{{ $t(onlyOneChild.meta.title) }}</span>
+        <div style="display: flex; align-items: center; overflow: hidden">
+          <span v-if="!menuMode">{{ $t(onlyOneChild.meta.title) }}</span>
+          <el-tooltip
+            v-else
+            placement="top"
+            :offset="-10"
+            :disabled="!onlyOneChild.showTooltip"
+          >
+            <template #content> {{ $t(onlyOneChild.meta.title) }} </template>
+            <span
+              ref="menuTextRef"
+              style="overflow: hidden; text-overflow: ellipsis"
+              @mouseover="hoverMenu(onlyOneChild)"
+            >
+              {{ $t(onlyOneChild.meta.title) }}
+            </span>
+          </el-tooltip>
           <Icon
             v-if="onlyOneChild.meta.extraIcon"
             :svg="onlyOneChild.meta.extraIcon.svg ? true : false"
@@ -84,10 +126,32 @@ function resolvePath(routePath) {
     popper-append-to-body
   >
     <template #title>
-      <el-icon v-show="props.item.meta.icon">
+      <el-icon v-show="props.item.meta.icon" :class="props.item.meta.icon"> 
         <component :is="props.item.meta && props.item.meta.icon"></component>
       </el-icon>
-      <span>{{ $t(props.item.meta.title) }}</span>
+      <span v-if="!menuMode">{{ $t(props.item.meta.title) }}</span>
+      <el-tooltip
+        v-else
+        placement="top"
+        :offset="-10"
+        :disabled="!props.item.showTooltip"
+      >
+        <template #content> {{ $t(props.item.meta.title) }} </template>
+        <div
+          ref="menuTextRef"
+          style="
+            display: inline-block;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            width: 125px;
+          "
+          @mouseover="hoverMenu(props.item)"
+        >
+          <span style="overflow: hidden; text-overflow: ellipsis">
+            {{ $t(props.item.meta.title) }}
+          </span>
+        </div>
+      </el-tooltip>
       <Icon
         v-if="props.item.meta.extraIcon"
         :svg="props.item.meta.extraIcon.svg ? true : false"

+ 6 - 1
src/layout/index.vue

@@ -16,6 +16,7 @@ import { useI18n } from "vue-i18n";
 import { routerArrays } from "./types";
 import { emitter } from "/@/utils/mitt";
 import { useEventListener } from "@vueuse/core";
+import backTop from "/@/assets/svg/back_top.svg";
 import { useAppStoreHook } from "/@/store/modules/app";
 import fullScreen from "/@/assets/svg/full_screen.svg";
 import exitScreen from "/@/assets/svg/exit_screen.svg";
@@ -195,7 +196,11 @@ const layoutHeader = defineComponent({
         <app-main :fixed-header="set.fixedHeader" />
       </div>
       <el-scrollbar v-else>
-        <el-backtop target=".main-container .el-scrollbar__wrap"></el-backtop>
+        <el-backtop
+          title="回到顶部"
+          target=".main-container .el-scrollbar__wrap"
+          ><backTop />
+        </el-backtop>
         <layout-header />
         <!-- 主体内容 -->
         <app-main :fixed-header="set.fixedHeader" />

+ 1 - 0
src/layout/types.ts

@@ -62,6 +62,7 @@ export type childrenType = {
       name?: string;
     };
   };
+  showTooltip?: boolean;
 };
 
 export type themeColorsType = {

+ 7 - 1
src/main.ts

@@ -4,6 +4,7 @@ import { setupStore } from "/@/store";
 import { getServerConfig } from "./config";
 import { createApp, Directive } from "vue";
 import { usI18n } from "../src/plugins/i18n";
+import { MotionPlugin } from "@vueuse/motion";
 import { useTable } from "../src/plugins/vxe-table";
 import { useElementPlus } from "../src/plugins/element-plus";
 import { injectResponsiveStorage } from "/@/utils/storage/responsive";
@@ -27,7 +28,12 @@ Object.keys(directives).forEach(key => {
 getServerConfig(app).then(async config => {
   injectResponsiveStorage(app, config);
   setupStore(app);
-  app.use(router).use(useElementPlus).use(useTable).use(usI18n);
+  app
+    .use(router)
+    .use(MotionPlugin)
+    .use(useElementPlus)
+    .use(useTable)
+    .use(usI18n);
   await router.isReady();
   app.mount("#app");
 });

+ 1 - 1
src/router/modules/components.ts

@@ -4,7 +4,7 @@ const componentsRouter = {
   path: "/components",
   name: "components",
   component: Layout,
-  redirect: "/components/split-pane",
+  redirect: "/components/video",
   meta: {
     icon: "Menu",
     title: "message.hscomponents",

+ 0 - 5
src/style/index.scss

@@ -65,11 +65,6 @@ ul {
   }
 }
 
-// main-container global css
-.app-container {
-  padding: 20px;
-}
-
 .login,
 .register {
   width: 100vw;

+ 3 - 2
src/style/sidebar.scss

@@ -27,13 +27,14 @@
     transition: margin-left 0.28s;
     margin-left: $sideBarWidth;
     position: relative;
+    background: #f0f2f5;
     @media screen and (min-width: 150px) and (max-width: 420px) {
-      .el-scrollbar__view {
+      .app-main .el-scrollbar__view:first-child {
         overflow-y: hidden;
       }
     }
     @media screen and (min-width: 420px) {
-      .el-scrollbar__view {
+      .app-main .el-scrollbar__view:first-child {
         overflow: hidden;
       }
     }

+ 8 - 20
src/utils/http/core.ts

@@ -41,12 +41,6 @@ class EnclosureHttp {
   // 记录当前这一次cancelToken的key
   private currentCancelTokenKey = "";
 
-  private beforeRequestCallback: EnclosureHttpRequestConfig["beforeRequestCallback"] =
-    undefined;
-
-  private beforeResponseCallback: EnclosureHttpRequestConfig["beforeResponseCallback"] =
-    undefined;
-
   public get cancelTokenList(): Array<cancelTokenType> {
     return this.sourceTokenList;
   }
@@ -126,9 +120,8 @@ class EnclosureHttp {
         this.cancelRepeatRequest();
         this.currentCancelTokenKey = cancelKey;
         // 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
-        if (typeof this.beforeRequestCallback === "function") {
-          this.beforeRequestCallback($config);
-          this.beforeRequestCallback = undefined;
+        if (typeof config.beforeRequestCallback === "function") {
+          config.beforeRequestCallback($config);
           return $config;
         }
         if (EnclosureHttp.initConfig.beforeRequestCallback) {
@@ -159,20 +152,21 @@ class EnclosureHttp {
     const instance = EnclosureHttp.axiosInstance;
     instance.interceptors.response.use(
       (response: EnclosureHttpResoponse) => {
+        const $config = response.config;
         // 请求每次成功一次就删除当前canceltoken标记
-        const cancelKey = EnclosureHttp.genUniqueKey(response.config);
+        const cancelKey = EnclosureHttp.genUniqueKey($config);
         this.deleteCancelTokenByCancelKey(cancelKey);
+
+        NProgress.done();
         // 优先判断post/get等方法是否传入回掉,否则执行初始化设置等回掉
-        if (typeof this.beforeResponseCallback === "function") {
-          this.beforeResponseCallback(response);
-          this.beforeResponseCallback = undefined;
+        if (typeof $config.beforeResponseCallback === "function") {
+          $config.beforeResponseCallback(response);
           return response.data;
         }
         if (EnclosureHttp.initConfig.beforeResponseCallback) {
           EnclosureHttp.initConfig.beforeResponseCallback(response);
           return response.data;
         }
-        NProgress.done();
         return response.data;
       },
       (error: EnclosureHttpError) => {
@@ -210,12 +204,6 @@ class EnclosureHttp {
       ...axiosConfig
     } as EnclosureHttpRequestConfig);
     // 单独处理自定义请求/响应回掉
-    if (axiosConfig?.beforeRequestCallback) {
-      this.beforeRequestCallback = axiosConfig.beforeRequestCallback;
-    }
-    if (axiosConfig?.beforeResponseCallback) {
-      this.beforeResponseCallback = axiosConfig.beforeResponseCallback;
-    }
     return new Promise((resolve, reject) => {
       EnclosureHttp.axiosInstance
         .request(config)

+ 1 - 1
src/views/components/contextmenu/index.vue

@@ -5,7 +5,7 @@ import menuDynamic from "./menuDynamic.vue";
 </script>
 
 <template>
-  <div style="margin: 10px">
+  <div>
     <el-row :gutter="24">
       <el-col :xs="24" :sm="10" :md="10" :lg="8" :xl="10">
         <!-- 基本使用 -->

+ 1 - 1
src/views/components/count-to/index.vue

@@ -3,7 +3,7 @@ import { ReNormalCountTo, ReboundCountTo } from "/@/components/ReCountTo";
 </script>
 
 <template>
-  <div style="margin: 10px">
+  <div>
     <el-row :gutter="24">
       <el-col :xs="24" :sm="12" :md="12" :lg="12" :xl="12">
         <el-card shadow="always">

+ 1 - 1
src/views/components/cropping/index.vue

@@ -25,7 +25,7 @@ const onCropper = (): void => {
 </script>
 
 <template>
-  <div style="margin: 10px">
+  <div>
     <div class="cropper-container">
       <Cropper ref="refCropper" :width="'40vw'" :src="img" />
       <img :src="cropperImg" class="croppered" v-if="cropperImg" />

+ 3 - 6
src/views/components/map/index.vue

@@ -3,14 +3,11 @@ import { Amap } from "/@/components/ReMap";
 </script>
 
 <template>
-  <div class="map">
-    <Amap />
-  </div>
+  <Amap />
 </template>
 
 <style scoped>
-.map {
-  width: 100%;
-  height: 89vh;
+.main-content {
+  margin: 0;
 }
 </style>

+ 0 - 4
src/views/components/seamless-scroll/index.vue

@@ -110,10 +110,6 @@ function changeDirection(val) {
 </template>
 
 <style lang="scss" scoped>
-.box-card {
-  margin: 10px;
-}
-
 .card-header {
   display: flex;
   justify-content: space-between;

+ 7 - 6
src/views/components/selector/index.vue

@@ -23,12 +23,7 @@ const selectedVal = ({ left, right }): void => {
 
 <template>
   <div>
-    <el-card
-      class="box-card"
-      style="margin: 10px"
-      v-for="(item, key) in dataLists"
-      :key="key"
-    >
+    <el-card class="box-card" v-for="(item, key) in dataLists" :key="key">
       <template #header>
         <div class="card-header">
           <span>{{ item.title }}</span>
@@ -44,3 +39,9 @@ const selectedVal = ({ left, right }): void => {
     </el-card>
   </div>
 </template>
+
+<style scoped>
+.el-card {
+  margin-bottom: 10px;
+}
+</style>

+ 2 - 3
src/views/components/split-pane/index.vue

@@ -41,12 +41,11 @@ const settingTB: ContextProps = reactive({
 
 <style lang="scss" scoped>
 $W: 100%;
-$H: 80vh;
+$H: 70vh;
 
 .split-pane {
-  width: 98%;
+  width: 70vw;
   height: $H;
-  margin-top: 5px;
   text-align: center;
   font-size: 50px;
   color: #fff;

+ 6 - 3
src/views/flow-chart/index.vue

@@ -86,9 +86,8 @@ onMounted(() => {
 
 <style scoped>
 #LF-Turbo {
-  width: 100vw;
-  height: 88.5vh;
-  outline: none;
+  width: 100%;
+  height: calc(100vh - 90px);
 }
 
 .logic-flow-view {
@@ -138,4 +137,8 @@ onMounted(() => {
   height: 85vh;
   overflow: auto;
 }
+
+.main-content {
+  margin: 0;
+}
 </style>

+ 1 - 1
src/views/nested/menu1/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="app-container">
+  <div>
     <p>{{ $t("message.hsmenu1") }}</p>
     <router-view>
       <template #default="{ Component, route }">

+ 1 - 1
src/views/nested/menu2/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="app-container">
+  <div>
     <p>{{ $t("message.hsmenu2") }}</p>
     <el-input v-model="input" />
   </div>

+ 1 - 1
src/views/permission/button/index.vue

@@ -14,7 +14,7 @@ function changRole(value) {
 </script>
 
 <template>
-  <div class="app-container">
+  <div>
     <el-radio-group v-model="auth" @change="changRole">
       <el-radio-button label="admin"></el-radio-button>
       <el-radio-button label="test"></el-radio-button>

+ 1 - 1
src/views/permission/page/index.vue

@@ -22,7 +22,7 @@ function changRole() {
 </script>
 
 <template>
-  <div class="app-container">
+  <div>
     <h4>
       当前角色:
       <span style="font-size: 26px">{{ purview }}</span>

+ 9 - 5
src/views/system/dict/index.vue

@@ -197,7 +197,7 @@ function handleClose() {
 </script>
 
 <template>
-  <div class="dict-container">
+  <div>
     <!-- 工具栏 -->
     <vxe-toolbar>
       <template #buttons>
@@ -309,10 +309,6 @@ function handleClose() {
 </template>
 
 <style lang="scss" scoped>
-.dict-container {
-  margin: 10px;
-}
-
 .vxe-input + .vxe-button,
 .vxe-input + .vxe-button--dropdown,
 .vxe-button + .vxe-button,
@@ -324,6 +320,14 @@ function handleClose() {
   border-radius: 0;
 }
 
+.vxe-toolbar.size--medium {
+  padding: 10px;
+}
+
+.vxe-table--render-default.size--medium {
+  margin-top: 12px;
+}
+
 .vxe-button.size--medium.type--button {
   margin-right: 0.07em;
 }

+ 2 - 29
src/views/system/user/index.vue

@@ -6,7 +6,7 @@ const gridOptions = reactive({
   border: true,
   resizable: true,
   keepSource: true,
-  height: 500,
+  height: 578,
   printConfig: {},
   importConfig: {},
   exportConfig: {},
@@ -162,33 +162,6 @@ const gridOptions = reactive({
                 sex: "Man ",
                 age: 35,
                 address: "Guangzhou"
-              },
-              {
-                id: 100011,
-                name: "Test11",
-                nickname: "T11",
-                role: "Test",
-                sex: "Women ",
-                age: 26,
-                address: "vxe-table 从入门到放弃"
-              },
-              {
-                id: 100012,
-                name: "Test12",
-                nickname: "T12",
-                role: "Develop",
-                sex: "Man ",
-                age: 34,
-                address: "Guangzhou"
-              },
-              {
-                id: 100013,
-                name: "Test13",
-                nickname: "T13",
-                role: "Test",
-                sex: "Women ",
-                age: 22,
-                address: "Shenzhen"
               }
             ];
             resolve({
@@ -238,5 +211,5 @@ const gridOptions = reactive({
 </script>
 
 <template>
-  <vxe-grid v-bind="gridOptions" style="width: 98%"></vxe-grid>
+  <vxe-grid v-bind="gridOptions"></vxe-grid>
 </template>

+ 176 - 92
src/views/welcome.vue

@@ -6,16 +6,14 @@ import {
   ReLine,
   ReBar
 } from "/@/components/ReCharts/index";
-import { useAppStoreHook } from "/@/store/modules/app";
-import { ref, shallowRef, computed, onBeforeMount } from "vue";
+import { ref, computed } from "vue";
 
 const date: Date = new Date();
 let loading = ref<boolean>(true);
-const componentList = shallowRef([]);
 
 setTimeout(() => {
   loading.value = !loading.value;
-}, 500);
+}, 800);
 
 let greetings = computed(() => {
   if (date.getHours() >= 0 && date.getHours() < 12) {
@@ -27,56 +25,6 @@ let greetings = computed(() => {
   }
 });
 
-onBeforeMount(() => {
-  if (useAppStoreHook().device === "mobile") {
-    componentList.value = [
-      {
-        width: "20em",
-        title: "GitHub饼图信息",
-        component: RePie
-      },
-      {
-        width: "20em",
-        title: "GitHub折线图信息",
-        component: ReLine
-      },
-      {
-        width: "20em",
-        title: "GitHub柱状图信息",
-        component: ReBar
-      }
-    ];
-  } else {
-    componentList.value = [
-      {
-        width: "43em",
-        title: "GitHub信息",
-        component: ReGithub
-      },
-      {
-        width: "43em",
-        title: "GitHub滚动信息",
-        component: ReInfinite
-      },
-      {
-        width: "28.28em",
-        title: "GitHub饼图信息",
-        component: RePie
-      },
-      {
-        width: "28.28em",
-        title: "GitHub折线图信息",
-        component: ReLine
-      },
-      {
-        width: "28.28em",
-        title: "GitHub柱状图信息",
-        component: ReBar
-      }
-    ];
-  }
-});
-
 const openDepot = (): void => {
   window.open("https://github.com/xiaoxian521/vue-pure-admin");
 };
@@ -95,27 +43,177 @@ const openDepot = (): void => {
       </div>
     </el-card>
 
-    <el-space class="space" wrap size="large">
-      <el-skeleton
-        v-for="(item, key) in componentList"
-        :key="key"
-        animated
-        :rows="7"
-        :loading="loading"
-        :class="$style.size"
-        :style="{ width: item.width }"
+    <el-row :gutter="24" style="margin: 20px">
+      <el-col
+        :xs="24"
+        :sm="24"
+        :md="12"
+        :lg="12"
+        :xl="12"
+        style="margin-bottom: 20px"
+        v-motion
+        :initial="{
+          opacity: 0,
+          y: 100
+        }"
+        :enter="{
+          opacity: 1,
+          y: 0,
+          transition: {
+            delay: 200
+          }
+        }"
+      >
+        <el-card>
+          <template #header>
+            <div>
+              <span>GitHub信息</span>
+            </div>
+          </template>
+          <el-skeleton animated :rows="7" :loading="loading">
+            <template #default>
+              <ReGithub />
+            </template>
+          </el-skeleton>
+        </el-card>
+      </el-col>
+
+      <el-col
+        :xs="24"
+        :sm="24"
+        :md="12"
+        :lg="12"
+        :xl="12"
+        style="margin-bottom: 20px"
+        v-motion
+        :initial="{
+          opacity: 0,
+          y: 100
+        }"
+        :enter="{
+          opacity: 1,
+          y: 0,
+          transition: {
+            delay: 200
+          }
+        }"
+      >
+        <el-card>
+          <template #header>
+            <div>
+              <span>GitHub滚动信息</span>
+            </div>
+          </template>
+          <el-skeleton animated :rows="7" :loading="loading">
+            <template #default>
+              <ReInfinite />
+            </template>
+          </el-skeleton>
+        </el-card>
+      </el-col>
+
+      <el-col
+        :xs="24"
+        :sm="24"
+        :md="12"
+        :lg="8"
+        :xl="8"
+        style="margin-bottom: 20px"
+        v-motion
+        :initial="{
+          opacity: 0,
+          y: 100
+        }"
+        :enter="{
+          opacity: 1,
+          y: 0,
+          transition: {
+            delay: 400
+          }
+        }"
+      >
+        <el-card>
+          <template #header>
+            <div>
+              <span>GitHub饼图信息</span>
+            </div>
+          </template>
+          <el-skeleton animated :rows="7" :loading="loading">
+            <template #default>
+              <RePie />
+            </template>
+          </el-skeleton>
+        </el-card>
+      </el-col>
+
+      <el-col
+        :xs="24"
+        :sm="24"
+        :md="12"
+        :lg="8"
+        :xl="8"
+        style="margin-bottom: 20px"
+        v-motion
+        :initial="{
+          opacity: 0,
+          y: 100
+        }"
+        :enter="{
+          opacity: 1,
+          y: 0,
+          transition: {
+            delay: 400
+          }
+        }"
       >
-        <template #default>
-          <div
-            :class="['echart-card', $style.size]"
-            :style="{ width: item.width }"
-          >
-            <h4>{{ item.title }}</h4>
-            <component :is="item.component"></component>
-          </div>
-        </template>
-      </el-skeleton>
-    </el-space>
+        <el-card>
+          <template #header>
+            <div>
+              <span>GitHub折线图信息</span>
+            </div>
+          </template>
+          <el-skeleton animated :rows="7" :loading="loading">
+            <template #default>
+              <ReLine />
+            </template>
+          </el-skeleton>
+        </el-card>
+      </el-col>
+
+      <el-col
+        :xs="24"
+        :sm="24"
+        :md="24"
+        :lg="8"
+        :xl="1"
+        style="margin-bottom: 20px"
+        v-motion
+        :initial="{
+          opacity: 0,
+          y: 100
+        }"
+        :enter="{
+          opacity: 1,
+          y: 0,
+          transition: {
+            delay: 400
+          }
+        }"
+      >
+        <el-card>
+          <template #header>
+            <div>
+              <span>GitHub柱状图信息</span>
+            </div>
+          </template>
+          <el-skeleton animated :rows="7" :loading="loading">
+            <template #default>
+              <ReBar />
+            </template>
+          </el-skeleton>
+        </el-card>
+      </el-col>
+    </el-row>
   </div>
 </template>
 
@@ -126,8 +224,11 @@ const openDepot = (): void => {
 </style>
 
 <style lang="scss" scoped>
+.main-content {
+  margin: 0;
+}
+
 .welcome {
-  width: 100%;
   height: 100%;
 
   .top-content {
@@ -155,22 +256,5 @@ const openDepot = (): void => {
       }
     }
   }
-
-  .space {
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    margin-left: 8px;
-    padding: 10px;
-
-    .echart-card {
-      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12), 0 0 6px rgba(0, 0, 0, 0.04);
-
-      h4 {
-        margin: 0;
-        padding: 20px;
-      }
-    }
-  }
 }
 </style>