Lechan Dai 2 years ago
parent
commit
4f1b525c36
82 changed files with 2130 additions and 122 deletions
  1. 2 1
      .eslintignore
  2. 3 0
      package.json
  3. BIN
      public/imgs/0.png
  4. BIN
      public/imgs/article-banner.png
  5. BIN
      public/imgs/article-detail-pic-1.png
  6. BIN
      public/imgs/avatar.png
  7. BIN
      public/imgs/email_icon.png
  8. BIN
      public/imgs/export-cover.png
  9. BIN
      public/imgs/export-qrcode.png
  10. BIN
      public/imgs/eye_close_icon.png
  11. BIN
      public/imgs/eye_icon.png
  12. BIN
      public/imgs/like-button-checked.png
  13. BIN
      public/imgs/like-button.png
  14. BIN
      public/imgs/login-banner.png
  15. BIN
      public/imgs/menu-arrow-1.png
  16. BIN
      public/imgs/menu-arrow.png
  17. BIN
      public/imgs/password_icon.png
  18. BIN
      public/imgs/personal_banner.png
  19. BIN
      public/imgs/required_icon.png
  20. BIN
      public/imgs/split-pic-1.png
  21. BIN
      public/imgs/split-pic-2.png
  22. BIN
      public/imgs/star-blank.png
  23. BIN
      public/imgs/star.png
  24. BIN
      public/imgs/user-collection.png
  25. BIN
      public/imgs/user-comment.png
  26. BIN
      public/imgs/user-history.png
  27. BIN
      public/imgs/user-like.png
  28. BIN
      public/imgs/user-order.png
  29. BIN
      public/imgs/user-personal-1.png
  30. 1 0
      public/imgs/user-personal-1.svg
  31. BIN
      public/imgs/user-personal.png
  32. 1 0
      public/imgs/user-personal.svg
  33. BIN
      public/imgs/user-setting-1.png
  34. BIN
      public/imgs/user-setting.png
  35. BIN
      public/imgs/user-subscription.png
  36. BIN
      public/imgs/user_icon.png
  37. BIN
      public/imgs/vcode_icon.png
  38. BIN
      public/imgs/vip-preset-bg.png
  39. 7 3
      src/App.vue
  40. BIN
      src/assets/css/fonts/element-icons.ttf
  41. BIN
      src/assets/css/fonts/element-icons.woff
  42. 1 0
      src/assets/css/index.css
  43. 20 0
      src/components.d.ts
  44. 7 2
      src/components/layout-basic/layout-basic.vue
  45. 37 0
      src/components/layout-user/layout-user-header.vue
  46. 108 0
      src/components/layout-user/layout-user-menu.vue
  47. 30 0
      src/components/layout-user/layout-user.vue
  48. 0 7
      src/components/shared/ButtonPrimary.vue
  49. 0 7
      src/components/shared/ButtonSecondary.vue
  50. 0 7
      src/components/shared/Heading1.vue
  51. 0 7
      src/components/shared/Heading2.vue
  52. 1 1
      src/components/ui-devider/ui-devider.vue
  53. 20 0
      src/components/ui-input/ui-input.vue
  54. 38 27
      src/components/ui-main-article/ui-main-article.vue
  55. 8 5
      src/components/ui-nav-bar/ui-nav-bar.vue
  56. 71 0
      src/components/ui-order-table/ui-order-table.vue
  57. 1 1
      src/components/ui-shadow-box/ui-shadow-box.vue
  58. 33 15
      src/components/ui-swiper/ui-swiper.vue
  59. 18 0
      src/components/ui-title-devider/ui-title-devider.vue
  60. 38 0
      src/components/ui-vip-preset/ui-vip-preset.vue
  61. 4 0
      src/main.js
  62. 356 0
      src/pages/article-detail/article-detail.vue
  63. 115 0
      src/pages/auth/change-password.vue
  64. 191 0
      src/pages/auth/login.vue
  65. 87 0
      src/pages/auth/profile-complete.vue
  66. 1 1
      src/pages/home/_components/home-tags.vue
  67. 73 14
      src/pages/home/home.vue
  68. 142 0
      src/pages/realtime-news/realtime-news.vue
  69. 142 0
      src/pages/recommend/recommend.vue
  70. 40 0
      src/pages/user/_components/user-account-setting-info-item.vue
  71. 71 0
      src/pages/user/user-account-setting.vue
  72. 21 0
      src/pages/user/user-collection.vue
  73. 20 0
      src/pages/user/user-comment.vue
  74. 20 0
      src/pages/user/user-history.vue
  75. 23 0
      src/pages/user/user-like.vue
  76. 146 0
      src/pages/user/user-order.vue
  77. 68 0
      src/pages/user/user-personal-center.vue
  78. 26 0
      src/pages/user/user-subscription.vue
  79. 44 1
      src/router/index.ts
  80. 3 3
      tailwind.config.js
  81. 20 20
      vite.config.ts
  82. 72 0
      yarn.lock

+ 2 - 1
.eslintignore

@@ -1,4 +1,5 @@
 dist
 public
 src
-/
+/
+vite.config.ts

+ 3 - 0
package.json

@@ -10,6 +10,9 @@
   "dependencies": {
     "@vueuse/core": "^9.0.0",
     "core-js": "^3.24.0",
+    "dom-to-image": "^2.6.0",
+    "element-ui": "^2.15.10",
+    "file-saver": "^2.0.5",
     "nanoid": "^4.0.0",
     "portal-vue": "^2.1.7",
     "swiper": "6.x",

BIN
public/imgs/0.png


BIN
public/imgs/article-banner.png


BIN
public/imgs/article-detail-pic-1.png


BIN
public/imgs/avatar.png


BIN
public/imgs/email_icon.png


BIN
public/imgs/export-cover.png


BIN
public/imgs/export-qrcode.png


BIN
public/imgs/eye_close_icon.png


BIN
public/imgs/eye_icon.png


BIN
public/imgs/like-button-checked.png


BIN
public/imgs/like-button.png


BIN
public/imgs/login-banner.png


BIN
public/imgs/menu-arrow-1.png


BIN
public/imgs/menu-arrow.png


BIN
public/imgs/password_icon.png


BIN
public/imgs/personal_banner.png


BIN
public/imgs/required_icon.png


BIN
public/imgs/split-pic-1.png


BIN
public/imgs/split-pic-2.png


BIN
public/imgs/star-blank.png


BIN
public/imgs/star.png


BIN
public/imgs/user-collection.png


BIN
public/imgs/user-comment.png


BIN
public/imgs/user-history.png


BIN
public/imgs/user-like.png


BIN
public/imgs/user-order.png


BIN
public/imgs/user-personal-1.png


File diff suppressed because it is too large
+ 1 - 0
public/imgs/user-personal-1.svg


BIN
public/imgs/user-personal.png


File diff suppressed because it is too large
+ 1 - 0
public/imgs/user-personal.svg


BIN
public/imgs/user-setting-1.png


BIN
public/imgs/user-setting.png


BIN
public/imgs/user-subscription.png


BIN
public/imgs/user_icon.png


BIN
public/imgs/vcode_icon.png


BIN
public/imgs/vip-preset-bg.png


+ 7 - 3
src/App.vue

@@ -1,6 +1,10 @@
 <template>
-  <div id="app" class="bg-[#F7F7F7]">
-    
-      <RouterView />
+  <div id="app" >
+    <RouterView />
   </div>
 </template>
+<style>
+body {
+  @apply bg-[#F7F7F7] ;
+}
+</style>

BIN
src/assets/css/fonts/element-icons.ttf


BIN
src/assets/css/fonts/element-icons.woff


File diff suppressed because it is too large
+ 1 - 0
src/assets/css/index.css


+ 20 - 0
src/components.d.ts

@@ -9,6 +9,18 @@ declare module '@vue/runtime-core' {
   export interface GlobalComponents {
     ButtonPrimary: typeof import('./components/shared/ButtonPrimary.vue')['default']
     ButtonSecondary: typeof import('./components/shared/ButtonSecondary.vue')['default']
+    ElButton: typeof import('element-ui/lib/button')['default']
+    ElDialog: typeof import('element-ui/lib/dialog')['default']
+    ElInput: typeof import('element-ui/lib/input')['default']
+    ElRadio: typeof import('element-ui/lib/radio')['default']
+    ElRadioGroup: typeof import('element-ui/lib/radio-group')['default']
+    ElSwitch: typeof import('element-ui/lib/switch')['default']
+    ElTable: typeof import('element-ui/lib/table')['default']
+    ElTableColumn: typeof import('element-ui/lib/table-column')['default']
+    ElTabPane: typeof import('element-ui/lib/tab-pane')['default']
+    ElTabs: typeof import('element-ui/lib/tabs')['default']
+    ElTextarea: typeof import('element-ui/lib/textarea')['default']
+    ElTextArea: typeof import('element-ui/lib/text-area')['default']
     Feature: typeof import('./components/Feature.vue')['default']
     Features: typeof import('./components/Features.vue')['default']
     Heading1: typeof import('./components/shared/Heading1.vue')['default']
@@ -18,6 +30,9 @@ declare module '@vue/runtime-core' {
     HomeNew: typeof import('./pages/home/_components/home-new.vue')['default']
     HomeTags: typeof import('./pages/home/_components/home-tags.vue')['default']
     LayoutBasic: typeof import('./components/layout-basic/layout-basic.vue')['default']
+    LayoutUser: typeof import('./components/layout-user/layout-user.vue')['default']
+    LayoutUserHeader: typeof import('./components/layout-user/layout-user-header.vue')['default']
+    LayoutUserMenu: typeof import('./components/layout-user/layout-user-menu.vue')['default']
     MdiAlien: typeof import('~icons/mdi/alien')['default']
     MdiArrowRight: typeof import('~icons/mdi/arrow-right')['default']
     MdiGithub: typeof import('~icons/mdi/github')['default']
@@ -27,12 +42,17 @@ declare module '@vue/runtime-core' {
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
     UiDevider: typeof import('./components/ui-devider/ui-devider.vue')['default']
+    UiInput: typeof import('./components/ui-input/ui-input.vue')['default']
     UiMainArticle: typeof import('./components/ui-main-article/ui-main-article.vue')['default']
     UiNavBar: typeof import('./components/ui-nav-bar/ui-nav-bar.vue')['default']
+    UiOrderTable: typeof import('./components/ui-order-table/ui-order-table.vue')['default']
     UiPortal: typeof import('./components/ui-portal/ui-portal.vue')['default']
     UiShadowBox: typeof import('./components/ui-shadow-box/ui-shadow-box.vue')['default']
     UiSmallArticle: typeof import('./components/ui-small-article/ui-small-article.vue')['default']
     UiSwiper: typeof import('./components/ui-swiper/ui-swiper.vue')['default']
+    UiTitleDevider: typeof import('./components/ui-title-devider/ui-title-devider.vue')['default']
     UiVipArticle: typeof import('./components/ui-vip-article/ui-vip-article.vue')['default']
+    UiVipPreset: typeof import('./components/ui-vip-preset/ui-vip-preset.vue')['default']
+    UserAccountSettingInfoItem: typeof import('./pages/user/_components/user-account-setting-info-item.vue')['default']
   }
 }

+ 7 - 2
src/components/layout-basic/layout-basic.vue

@@ -1,10 +1,15 @@
 <template>
-  <div class="w-screen flex h-screen flex-col items-center">
+  <div class="w-screen flex  flex-col items-center overflow-x-hidden">
     <ui-nav-bar></ui-nav-bar>
-    <div class="flex-1 overflow-y-auto">
+    <div >
       <RouterView />
     </div>
+    <div class="h-70px"></div>
+    <div class="!h-452px w-full bg-primary">
+      12312
+    </div>  
   </div>
+
 </template>
 
 <script>

+ 37 - 0
src/components/layout-user/layout-user-header.vue

@@ -0,0 +1,37 @@
+<template>
+  <div
+    style="background: url('/imgs/personal_banner.png'); background-size: cover"
+    class="w-full h-220px relative"
+  >
+    <div
+      class="w-full h-full bg-[rgba(18, 64, 38, 1)] backdrop-filter backdrop-blur-md"
+    ></div>
+    <div class="flex items-center absolute bottom-0 right-0 left-0 top-0">
+      <div class="w-1200px m-auto flex items-center justify-between px-70px">
+        <div class="flex items-center">
+          <div
+            class="w-120px h-120px rounded-full border-white border-1px border-solid mr-20px"
+          >
+            <img src="/imgs/avatar.png" class="object-cover w-full h-full" />
+          </div>
+
+          <div>
+            <div class="text-size-20px text-white">cyt</div>
+            <div class="h-26px"></div>
+            <div class="text-size-16px text-white">2342342332@qq.com</div>
+          </div>
+        </div>
+        <div class="flex items-center">
+          <div class="text-white text-size-18px mr-19px">
+            {{ $t("当前为月会员,有效期至2022年9月28日") }}
+          </div>
+          <div
+            class="text-size-14px text-white w-80px h-30px bg-primary flex items-center justify-center rounded-full"
+          >
+            续 费
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>

+ 108 - 0
src/components/layout-user/layout-user-menu.vue

@@ -0,0 +1,108 @@
+<template>
+  <div class="w-240px h-auto bg-white px-39px pt-76px">
+    <div
+      v-for="(menu, index) in menus"
+      :key="index"
+      class="flex items-center mb-57px cursor-pointer"
+      @click="$router.push(menu.route)"
+    >
+      <img
+        :src="currentMenuIndex === index ? menu.activeIcon : menu.icon"
+        class="w-30px h-30px object-contain mr-13px"
+      />
+      <div
+        :class="`text-size-20px ${
+          currentMenuIndex === index ? 'text-primary' : 'text-black'
+        } ${currentMenuIndex === index ? 'font-normal' : 'font-normal'}`"
+      >
+        {{ $t(menu.name) }}
+      </div>
+      <div class="flex flex-1 items-center justify-end">
+        <img
+          :src="
+            currentMenuIndex === index ? '/imgs/menu-arrow-1.png' : '/imgs/menu-arrow.png'
+          "
+          class="w-6px"
+        />
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  watch: {
+    $route: function (next) {
+      console.log(next.path);
+      this.currentPath = next.path;
+    },
+  },
+  computed: {
+    currentMenuIndex: (vm) => vm.menus.findIndex((menu) => menu.route === vm.currentPath),
+  },
+  mounted() {
+    console.log("currentMenuIndex", this.currentMenuIndex);
+  },
+
+  data() {
+    return {
+      currentPath: this.$route.path,
+      menus: [
+        {
+          icon: "/imgs/user-personal.png",
+          activeIcon: "/imgs/user-personal-1.png",
+          name: "个人中心",
+          route: "/user/personal-center",
+        },
+        {
+          icon: "/imgs/user-setting.png",
+          activeIcon: "/imgs/user-setting-1.png",
+          name: "账号设置",
+          route: "/user/account-setting",
+        },
+        {
+          icon: "/imgs/user-order.png",
+          activeIcon: "/imgs/user-setting-1.png",
+          name: "我的订单",
+          route: "/user/order",
+        },
+        {
+          icon: "/imgs/user-collection.png",
+          activeIcon: "/imgs/user-collection-1.png",
+
+          name: "我的收藏",
+          route: "/user/collection",
+        },
+        {
+          icon: "/imgs/user-subscription.png",
+          activeIcon: "/imgs/user-subscription-1.png",
+
+          name: "我的订阅",
+          route: "/user/subscription",
+        },
+        {
+          icon: "/imgs/user-like.png",
+          activeIcon: "/imgs/user-like-1.png",
+
+          name: "我的点赞",
+          route: "/user/like",
+        },
+        {
+          icon: "/imgs/user-comment.png",
+          activeIcon: "/imgs/user-comment-1.png",
+
+          name: "我的评论",
+          route: "/user/comment",
+        },
+        {
+          icon: "/imgs/user-history.png",
+          activeIcon: "/imgs/user-history-1.png",
+
+          name: "浏览记录",
+          route: "/user/history",
+        },
+      ],
+    };
+  },
+};
+</script>

+ 30 - 0
src/components/layout-user/layout-user.vue

@@ -0,0 +1,30 @@
+<template>
+  <div class="w-screen">
+    <layout-user-header></layout-user-header>
+    <div class="h-27px"></div>
+
+    <div class="w-1200px flex m-auto">
+      <layout-user-menu :currentPath="currentPath"></layout-user-menu>
+      <div class="w-15px"></div>
+      <div class="w-940px bg-white">
+        <RouterView></RouterView>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  
+  data() {
+    return {
+      currentPath: this.$route.path,
+    };
+  },
+  beforeRouteEnter(to, from, next) {
+    next((vm) => {
+      vm.currentPath = to.path;
+    });
+  },
+};
+</script>

+ 0 - 7
src/components/shared/ButtonPrimary.vue

@@ -1,7 +0,0 @@
-<template>
-  <button
-    class="inline-flex px-6 py-2 text-lg text-white bg-green-500 border-0 rounded focus:outline-none hover:bg-green-400"
-  >
-    <slot />
-  </button>
-</template>

+ 0 - 7
src/components/shared/ButtonSecondary.vue

@@ -1,7 +0,0 @@
-<template>
-  <button
-    class="inline-flex px-6 py-2 ml-4 text-lg text-gray-700 bg-gray-200 border-0 rounded focus:outline-none hover:bg-gray-100"
-  >
-    <slot />
-  </button>
-</template>

+ 0 - 7
src/components/shared/Heading1.vue

@@ -1,7 +0,0 @@
-<template>
-  <h1
-    class="title-font sm:text-4xl text-3xl mb-4 font-medium text-gray-900 dark:text-white"
-  >
-    <slot />
-  </h1>
-</template>

+ 0 - 7
src/components/shared/Heading2.vue

@@ -1,7 +0,0 @@
-<template>
-  <h2
-    class="text-lg font-medium text-gray-900 sm:text-xl title-font dark:text-white"
-  >
-    <slot />
-  </h2>
-</template>

+ 1 - 1
src/components/ui-devider/ui-devider.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="w-full h-2px bg-[#f7f7f7]">
+    <div class="w-full h-2px bg-[#f7f7f7]" v-bind="$attrs">
 
     </div>
 </template>

+ 20 - 0
src/components/ui-input/ui-input.vue

@@ -0,0 +1,20 @@
+<template>
+  <el-input v-bind="$attrs" class="!w-auto !rounded-full h-40px ui-input">
+    <template v-for="slot in Object.entries(this.$slots)" :slot="slot[0]">
+      <slot :name="slot[0]"></slot>
+    </template>
+  </el-input>
+</template>
+
+<script>
+export default {};
+</script>
+
+<style>
+.ui-input .el-input__inner {
+  border-radius: 100px !important;
+  padding: 0 20px;
+  height: 100%;
+  widows: 100%;
+}
+</style>

+ 38 - 27
src/components/ui-main-article/ui-main-article.vue

@@ -1,37 +1,48 @@
 <template>
+  <ui-shadow-box v-bind="$attrs" class="relative">
     <div class="flex bg-white pl-16px pr-14px items-center h-165px">
-        <div class="relative">
-            <img class="w-250px h-140px object-cover" src="/imgs/article_cover1.png"/>
-            <div class="absolute left-0 top-0 text-white text-size-12px">
-                <img class=" w-60px h-auto" src="/imgs/cover-tag.png"/>
-                <span class="absolute top-0 h-full  w-full  flex items-center ml-6px ">VIP尊享</span>
-            </div>
+      <div class="relative">
+        <img class="w-250px h-140px object-cover" src="/imgs/article_cover1.png" />
+        <div class="absolute left-0 top-0 text-white text-size-12px">
+          <img class="w-60px h-auto" src="/imgs/cover-tag.png" />
+          <span class="absolute top-0 h-full w-full flex items-center ml-6px"
+            >VIP尊享</span
+          >
         </div>
-        <div class="w-19px"></div>
-        <div class="flex flex-col flex-1 h-full">
-            <div class="h-18px"></div>
-            <div class="text-size-20px text-[#000A04] font-thin">
-                这里是轮播图推荐内容标题这里是轮播图推荐内容标题
-            </div>
-            <div class="h-23px"></div>
-            <div class="text-[#686868] text-size-16px font-normal leading-20px h-40px">这里是文章简介内容这里是文章简介内容这里是文章简介内容这里是文章简介内
-容这里是文这里是文章简介内容这里是文章简介内容这里是文章简介内容这......</div>
-<div class="h-32px"></div>
-            <div class="flex w-full">
-                <div class="text-[#B8B8B8] text-size-14px font-normal">香港特派员赵圆松</div>
-                <div class="text-[#B8B8B8] text-size-14px font-normal flex"><img class="w-18px h-auto" src="/imgs/time.png"/>2022-08-09</div>
-                <div class="text-[#B8B8B8] text-size-14px font-medium">2803浏览</div>
-            </div>
+      </div>
+      <div class="w-19px"></div>
+      <div class="flex flex-col flex-1 h-full">
+        <div class="h-18px"></div>
+        <div class="text-size-20px text-[#000A04] font-thin">
+          这里是轮播图推荐内容标题这里是轮播图推荐内容标题
         </div>
+        <div class="h-23px"></div>
+        <div class="text-[#686868] text-size-16px font-normal leading-20px h-40px">
+          这里是文章简介内容这里是文章简介内容这里是文章简介内容这里是文章简介内
+          容这里是文这里是文章简介内容这里是文章简介内容这里是文章简介内容这......
+        </div>
+        <div class="h-32px"></div>
+        <div class="flex w-full items-center">
+          <div class="text-[#B8B8B8] text-size-14px font-normal">香港特派员赵圆松</div>
+          <div class="flex items-center ml-76px">
+            <img class="w-18px h-auto" src="/imgs/time.png" />
+            <div class="text-[#B8B8B8] text-size-14px font-normal ml-5px">2022-08-09</div>
+          </div>
+          <div
+            v-if="!$slots.right"
+            class="text-[#B8B8B8] text-size-14px font-medium ml-auto"
+          >
+            2803浏览
+          </div>
+          <slot name="right"></slot>
+        </div>
+      </div>
     </div>
+  </ui-shadow-box>
 </template>
 
 <script>
-    export default {
-        
-    }
+export default {};
 </script>
 
-<style >
-
-</style>
+<style></style>

+ 8 - 5
src/components/ui-nav-bar/ui-nav-bar.vue

@@ -1,7 +1,9 @@
 <template>
-  <div class="h-80px w-screen bg-primary overflow-hidden">
-    <div class="flex h-full items-center">
-      <div class="w-379px"></div>
+  <div
+    class="h-80px w-screen bg-primary flex justify-center overflow-hidden items-center"
+  >
+    <div class="flex items-center h-full">
+      <!-- <div class="w-14px"></div> -->
       <div class="menu-item selected">
         {{ $t("首页") }}
       </div>
@@ -17,12 +19,12 @@
       <div class="menu-item">{{ $t("关于我们") }}</div>
       <div class="w-260px"></div>
       <div class="menu-item">
-        <img class="w-30px object-contain" src="/tougao.png" />
+        <img class="w-30px object-contain" src="/imgs/tougao.png" />
         {{ $t("投稿") }}
       </div>
       <div class="w-36px"></div>
       <div class="menu-item">
-        <img class="w-30px object-contain" src="/search.png" />
+        <img class="w-30px object-contain" src="/imgs/search.png" />
         {{ $t("搜索") }}
       </div>
       <div class="w-40px"></div>
@@ -61,5 +63,6 @@ export default {
   bottom: 14px;
   left: 0;
   border-radius: 3px;
+  
 }
 </style>

+ 71 - 0
src/components/ui-order-table/ui-order-table.vue

@@ -0,0 +1,71 @@
+<template>
+  <div>
+    <el-table
+      class="header-table"
+      header-cell-class-name="!bg-[#F7F7F7] font-normal text-size-14px "
+      header-row-class-name="h-50px"
+      :data="[]"
+      style="width: 100%"
+    >
+      <el-table-column v-for="(item, index) in columns" :key="index" v-bind="item">
+      </el-table-column>
+    </el-table>
+    <div class="h-20px"></div>
+    <div v-for="(item, index) in data" :key="index" class="mb-20px">
+      <div class="h-50px bg-[#F7F7F7] flex justify-between items-center px-10px">
+        <div class="text-black whitespace-nowrap text-left">hy645586466152123</div>
+        <div class="text-black text-left whitespace-nowrap">2022-08-30 09:35:30</div>
+      </div>
+      <el-table
+        header-cell-class-name="!bg-[#F7F7F7] font-normal text-size-14px "
+        header-row-class-name="data-header"
+        :data="[item]"
+        style="width: 100%"
+        :show-header="false"
+      >
+        <el-table-column v-for="(item, index) in columns" :key="index" v-bind="item">
+          <template v-slot:header>
+            <div v-if="index === 0" class="text-black whitespace-nowrap text-left">
+              hy645586466152123
+            </div>
+            <div
+              v-if="index === columns.length - 1 && index > 0"
+              class="text-black text-left whitespace-nowrap"
+            >
+              2022-08-30 09:35:30
+            </div>
+          </template>
+          <template v-slot:default="props" v-if="$scopedSlots[index] || $slots[index]">
+            <slot :name="index" v-bind="props"> </slot>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    columns: {
+      default: [],
+    },
+    data: [],
+  },
+  mounted() {
+    console.log("this.slot", this.$scopedSlots);
+  },
+};
+</script>
+
+<style>
+.header-table .el-table__body-wrapper {
+  display: none;
+}
+.data-header > th:first-child {
+  @apply absolute z-50;
+}
+.data-header > th:last-child {
+  /* @apply  absolute z-50;  */
+}
+</style>

+ 1 - 1
src/components/ui-shadow-box/ui-shadow-box.vue

@@ -1,5 +1,5 @@
 <template>
-  <div  class="rounded-3px shadow-[0px 3px 6px 0px rgba(0, 0, 0, 0.1)] bg-white">
+  <div v-bind="$attrs"  class="rounded-3px shadow bg-white">
       
     <slot></slot>
   </div>

+ 33 - 15
src/components/ui-swiper/ui-swiper.vue

@@ -1,21 +1,27 @@
 <template>
-  <div v-bind="$attrs" class="relative">
+  <div v-bind="$attrs" class="relative w-full">
     <swiper ref="swiper" class="relative w-full h-full" :options="swiperOption">
       <swiper-slide v-for="(item, index) in items" :key="index">
         <div class="w-full h-full absolute bg-[rgba(0,0,0,0.3)]"></div>
         <img class="w-full h-full object-cover" :src="item.url" />
+
+        <div
+          :class="`absolute bottom-23px left-26px font-normal z-50 flex text-white text-size-20px ${
+            titleClass ?? ''
+          }`"
+        >
+          {{ item.title }}
+        </div>
       </swiper-slide>
     </swiper>
-    <div class="absolute bottom-22px right-12px z-50 flex">
+    <div v-if="showPagination" :class="`absolute bottom-22px right-12px z-50 flex ${paginationclass}`">
       <div
+        @click="clickPagination(index)"
         v-for="(item, index) in items"
         :key="index"
         :class="`dot ${index === activeIndex ? 'selected' : ''}`"
       ></div>
     </div>
-    <div class="absolute bottom-23px left-26px font-normal z-50 flex text-white">
-      <div class="text-size-20">這裏是輪播圖推薦內容標題</div>
-    </div>
   </div>
 </template>
 
@@ -24,10 +30,9 @@ import { nanoid } from "nanoid";
 import { Swiper, SwiperSlide } from "vue-awesome-swiper";
 import "swiper/swiper-bundle.min.css";
 
-import SwiperCore, { Pagination } from "swiper/core";
+import SwiperCore, { Autoplay } from "swiper/core";
+SwiperCore.use([Autoplay]);
 
-// install Swiper modules
-SwiperCore.use([Pagination]);
 export default {
   components: {
     Swiper,
@@ -37,13 +42,24 @@ export default {
     items: {
       default: [],
     },
+    showPagination: {
+      default: false,
+    },
+    paginationclass:{
+      default: ''
+    } ,
+    titleClass: {},
   },
   computed: {
     paginationId: () => nanoid(6),
     swiperOption: () => ({
       slidesPerView: 1,
-
+      click: false,
       // loop: true,
+      autoplay: {
+        delay: 2000,
+        // pauseOnMouseEnter: true,
+      },
     }),
   },
 
@@ -54,14 +70,16 @@ export default {
   },
 
   methods: {
-    change(index) {
-      console.log(index);
+    change(swiper) {
+      if (!this.showPagination) return;
+      this.activeIndex = swiper.activeIndex;
+    },
+    clickPagination(index) {
+      this.$refs.swiper.$swiper.slideTo(index);
     },
   },
   mounted() {
-    this.$refs.swiper.$swiper.on("activeIndexChange", (swiper) => {
-      this.activeIndex = swiper.activeIndex;
-    });
+    this.$refs.swiper.$swiper.on("activeIndexChange", this.change);
   },
 };
 </script>
@@ -73,7 +91,7 @@ export default {
   @apply bg-rgba(255,255,255,1);
 }
 .dot {
-  @apply w-12px h-12px rounded-full bg-[rgba(255,255,255,0.3)] mr-10px;
+  @apply w-12px h-12px rounded-full bg-[rgba(255,255,255,0.3)] mr-10px cursor-pointer;
 }
 .dot.selected {
   @apply bg-white;

+ 18 - 0
src/components/ui-title-devider/ui-title-devider.vue

@@ -0,0 +1,18 @@
+<template>
+  <div class="pl-17px text-size-20px font-thin">
+    <div>{{ $t(title) }}</div>
+    <div class="h-14.5px"></div>
+    <ui-devider v-if="showBorder"></ui-devider>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    title: {},
+    showBorder: {
+      default: true,
+    },
+  },
+};
+</script>

+ 38 - 0
src/components/ui-vip-preset/ui-vip-preset.vue

@@ -0,0 +1,38 @@
+<template>
+  <div class="preset relative">
+    <div class="m-auto mt-25px w-227.74px relative">
+      <img src="/imgs/vip-preset-bg.png" class="w-full h-auto" />
+      <div class="absolute top-0 left-0 flex flex-col items-center w-full h-full">
+        <div class="text-size-20px text-primary font-light mb-11px mt-11px">月会员</div>
+        <div class="text-size-15px text-black mb-30px">30天</div>
+        <div class="text-size-15px text-[#686868] mb-38px">原价88元/月,现7.8折</div>
+        <div class="text-size-25px text-primary font-light">仅39元</div>
+      </div>
+    </div>
+    <div class="absolute flex flex-col w-full items-center bottom-25px">
+      <div class="w-204px text-size-14px leading-20px">
+        会员权益说明内容会员权益说明内容会员权益说明内容会员权益说明内容会员权益说明内容会员权益说明内容
+      </div>
+      <div
+        class="w-168px h-34px rounded-full text-primary border-1px border-solid border-primary flex items-center justify-center cursor-pointer"
+      >
+        立即开通
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {};
+</script>
+
+<style>
+.preset {
+  @apply w-253px h-367px;
+  /* 矩形 145 */
+
+  border-radius: 3px;
+
+  box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.1);
+}
+</style>

+ 4 - 0
src/main.js

@@ -6,7 +6,11 @@ import 'virtual:windi.css'
 import router from "@/router";
 import zhCN from "./locales/zh-CN";
 import zhTW from "./locales/zh-TW";
+import ElementUI from 'element-ui';
+import 'element-ui/lib/theme-chalk/index.css';
+import '@/assets/css/index.css'
 
+Vue.use(ElementUI);
 
 Vue.config.productionTip = false;
 Vue.config.devtools = true;

+ 356 - 0
src/pages/article-detail/article-detail.vue

@@ -0,0 +1,356 @@
+<template>
+  <div class="w-1200px detail">
+    <img src="/imgs/article-banner.png" class="my-20px" />
+    <div class="flex">
+      <div class="left mr-20px w-860px">
+        <ui-shadow-box class="w-full bg-white h-auto px-30px pt-30px mb-14px">
+          <div class="text-size-24px text-[#000] font-thin mb-27px">
+            这里是文章标题这里是文章标题,文章标题
+          </div>
+          <div
+            class="flex text-[#B8B8B8] text-size-14px items-center justify-between mb-33px"
+          >
+            <div class="flex items-center">
+              <div>香港特派员赵圆松</div>
+              <div class="ml-48px flex items-center">
+                <img class="w-18px h-auto mr-8px" src="/imgs/time.png" />
+                <span>2022-08-26</span>
+              </div>
+            </div>
+            <div class="flex items-center">
+              <div class="mr-48px">5评论</div>
+              <div class="mr-48px">10点赞</div>
+              <div class="mr-48px">56收藏</div>
+              <div>36582浏览</div>
+            </div>
+          </div>
+          <div
+            class="bg-[#F7F7F7] p-24px text-[#686868] text-size-16px leading-32px whitespace-pre-wrap mb-30px"
+          >
+            <p class="indent-32px">
+              这里是文章简介或摘要内容,这里是文章简介或摘要内容这里是文章简介或摘要内容,这里是文章简介
+              或摘容,这里是文章简介或摘要内容,这里是文章简介或摘要内容这里是文章简介或摘要内容。这里是文章
+              简介或摘要内容,这里是文章简介或摘要内容,这里是文章简介或摘要内容这里是文章简介或摘要内容。
+            </p>
+          </div>
+          <div class="content" v-html="html"></div>
+          <div
+            class="p-24px bg-[#f7f7f7] text-[#686868] leading-32px text-size-16px mb-30px"
+          >
+            <p>作者:香港特派员赵圆松;期刊:尖瑞科技期刊(ID:business-data)</p>
+            <p>本文由 @商业数据派 原创发布于杂志期刊,未经许可,禁止转载。</p>
+            <p>题图来自 Unsplash,基于CC0协议</p>
+          </div>
+          <div class="flex justify-center mb-30px">
+            <el-button type="primary" round class="h-40px w-400px"
+              >成为会员,查看更多精彩内容!</el-button
+            >
+          </div>
+          <ui-devider class="mb-30px"></ui-devider>
+          <div class="flex items-center justify-between">
+            <div class="flex">
+              <el-switch v-model="subscriped" inactive-color="#E1E1E1" class="mr-10px">
+              </el-switch>
+
+              <div class="text-size-16px">开启订阅,将为您推荐同类精彩内容!</div>
+            </div>
+            <div class="flex items-center">
+              <el-button class="action-button done" round> 收藏 | 2 </el-button>
+              <el-button class="action-button" round> 点赞 | 20 </el-button>
+              <el-button @click="exportVisible = true" class="action-button" round>
+                分享
+              </el-button>
+            </div>
+          </div>
+          <div class="h-46px"></div>
+        </ui-shadow-box>
+        <ui-shadow-box class="px-30px pt-37px pb-44px">
+          <div class="flex justify-between items-center mb-18px">
+            <div class="flex items-center">
+              <div class="text-size-24px mr-12px">{{ $t("评论") }}</div>
+              <div class="text-size-14px text-[#686868]">
+                {{ $t("文明上网,理性发言!") }}
+              </div>
+            </div>
+            <div class="text-size-14px text-primary">123{{ $t("条评论") }}</div>
+          </div>
+          <el-input
+            class="!bg-[#F7F7F7] h-100px mb-20px"
+            type="textarea"
+            :rows="2"
+            :placeholder="$t('我来说两句')"
+            v-model="textarea"
+          >
+          </el-input>
+          <div class="flex justify-end mb-14px">
+            <el-button type="primary" class="text-white h-30px !py-0" round
+              >发布</el-button
+            >
+          </div>
+          <div class="text-size-20px mb-16px">全部评论</div>
+          <ui-devider></ui-devider>
+          <div v-for="item in 4" :key="item">
+            <div class="flex items-start py-30px">
+              <img class="w-60px h-60px round" src="/imgs/avatar.png" />
+              <div class="mt-8px ml-14px">
+                <div class="flex mb-14px items-center">
+                  <div class="font-extralight text-size-16px mr-30px">用户名</div>
+                  <div class="text-size-14px text-[#B8B8B8]">2022-08-26 06:53</div>
+                </div>
+                <div class="text-[#686868] leading-20px text-size-14px">
+                  评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容评论内容
+                </div>
+              </div>
+            </div>
+            <ui-devider></ui-devider>
+          </div>
+          <div class="flex justify-center">
+            <el-button type="text" class="!text-[#686868]">查看更多评论</el-button>
+          </div>
+        </ui-shadow-box>
+      </div>
+
+      <div class="right w-320px">
+        <div class="px-20px bg-white">
+          <div class="h-17px"></div>
+          <div class="relative inline-flex mb-6.5px">
+            <img src="/imgs/hot.png" class="w-24px h-auto mr-4px" />
+            <div class="font-thin text-[#000] text-size-20px">{{ $t("热榜文章") }}</div>
+
+            <div
+              class="w-full h-3px absolute left-0 bottom-[-7.5px] bg-primary rounded-full"
+            ></div>
+          </div>
+          <ui-devider></ui-devider>
+          <div class="h-21px"></div>
+          <ui-swiper
+            class="mb-20px"
+            :items="[
+              { url: 'imgs/article_cover1.png', title: '这是标题' },
+              { url: 'imgs/article_cover1.png', title: '这是标题' },
+            ]"
+            titleClass="swiper-title"
+          ></ui-swiper>
+          <ui-devider></ui-devider>
+
+          <div v-for="item in 9" :key="item">
+            <ui-small-article></ui-small-article>
+            <ui-devider></ui-devider>
+          </div>
+        </div>
+        <div class="h-20px"></div>
+        <div class="px-20px bg-white">
+          <div class="h-17px"></div>
+          <div class="relative flex mb-6.5px justify-between item-center">
+            <div class="inline-flex">
+              <img src="/imgs/vip.png" class="w-24px h-auto mr-4px" />
+              <div class="font-thin text-[#000] text-size-20px">
+                {{ $t("VIP期刊") }}
+              </div>
+            </div>
+            <el-button
+              type="text"
+              class="!p-0 !text-size-14px !font-normal !text-[#686868]"
+              >查看更多</el-button
+            >
+
+            <div
+              class="w-full h-3px absolute left-0 bottom-[-7.5px] bg-primary rounded-full"
+            ></div>
+          </div>
+          <ui-devider></ui-devider>
+          <div class="h-21px"></div>
+
+          <ui-swiper
+            class="mb-20px"
+            :items="[
+              { url: 'imgs/article_cover1.png', title: '这是标题' },
+              { url: 'imgs/article_cover1.png', title: '这是标题' },
+            ]"
+            titleClass="swiper-title"
+          ></ui-swiper>
+          <ui-swiper
+            class="mb-20px"
+            :items="[
+              { url: 'imgs/article_cover1.png', title: '这是标题' },
+              { url: 'imgs/article_cover1.png', title: '这是标题' },
+            ]"
+            titleClass="swiper-title"
+          ></ui-swiper>
+          <ui-devider></ui-devider>
+          <div v-for="item in 10" :key="item">
+            <ui-vip-article></ui-vip-article>
+            <ui-devider></ui-devider>
+          </div>
+        </div>
+      </div>
+    </div>
+    <el-dialog @close="exportVisible = false" :visible="exportVisible" width="1200px">
+      <div class="w-full">
+        <div class="flex items-center mb-60px">
+          <div class="flex-1 text-right mr-70px">{{ $t("分享链接") }}:</div>
+          <div class="flex-1">https://daohang.qq.com/?fr=hmpage</div>
+          <div class="flex-1 ml-84px">
+            <el-button
+              class="!font-normal !text-white !bg-primary !w-120px !h-40px"
+              round
+              >{{ $t("复制链接") }}</el-button
+            >
+          </div>
+        </div>
+        <div class="flex items-start">
+          <div class="flex-1 text-right mr-70px">{{ $t("分享海报") }}:</div>
+          <div class="flex-1">
+            <ui-shadow-box ref="post" class="px-24px py-38px flex flex-col items-center">
+              <div class="font-extralight text-primary text-size-20px mb-28px">
+                {{ $t("杂志期刊") }}
+              </div>
+              <img src="/imgs/export-cover.png" class="w-310px h-auto mb-24px" />
+              <div class="text-size-16px text-[#000A04] mb-32px">
+                这里是轮播图推荐内容标题这里是轮播图推荐内容标题...
+              </div>
+              <div class="text-size-14px text-[#686868] mb-24px">
+                这里是文章简介内容这里是文章简介内容这里是文章简介内容这里是文章简介内容这里是文这里是文章简介内容这里是文章简介内容这里是文章简介内容这......
+              </div>
+              <div class="flex items-center w-full justify-end">
+                <div class="mr-10px text-[#B8B8B8] text-size-14px">
+                  <div class="mb-10px">作者:香港特派员赵圆松</div>
+                  <div class="text-right">时间:2022-08-26</div>
+                </div>
+                <img src="/imgs/export-qrcode.png" class="w-64px h-64px" />
+              </div>
+            </ui-shadow-box>
+          </div>
+          <div class="flex-1 ml-84px">
+            <el-button
+              @click="exportPost"
+              class="!font-normal !text-white !bg-primary !w-120px !h-40px"
+              round
+              >{{ $t("复制海报") }}</el-button
+            >
+          </div>
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import FileSaver from "file-saver";
+import domtoimage from "dom-to-image";
+export default {
+  methods: {
+    async exportPost() {
+      console.log(
+        "%c [ this.$refs.post ]-245",
+        "font-size:13px; background:pink; color:#bf2c9f;",
+        this.$refs.post.$el
+      );
+      const url = await domtoimage.toPng(this.$refs.post.$el, { filter: false });
+
+      FileSaver.saveAs(url, "post.png");
+    },
+  },
+  data() {
+    return {
+      exportVisible: false,
+      subscriped: true,
+      html: `<p><span style="font-size:16px">据央视新闻7月22日消息,俄罗斯国防部发言人科纳申科夫21日通报说,俄军在尼古拉耶夫和克拉玛托尔斯克打击了乌军多个指挥所。</span></p>
+
+<p>&nbsp;</p>
+
+<p>&nbsp;</p>
+
+<p><span style="font-size:16px"><img alt="" src="/imgs/article-detail-pic-1.png" style="width:100%" /></span></p>
+
+<p>&nbsp;</p>
+
+<p><span style="font-size:16px">据央视新闻7月22日消息,俄罗斯国防部发言人科纳申科夫21日通报说,俄军在尼古拉耶夫和克拉玛托尔斯克打击了乌军多个指挥所。</span></p>
+
+<p>&nbsp;</p>
+
+<p>&nbsp;</p>
+
+<p><span style="font-size:16px">另据央视新闻报道称,当地时间21日,欧洲理事会公布了针对俄罗斯的新制裁措施,包括禁止进口来自俄罗斯金和珠宝;增加了俄罗斯可用于军用的物资和技术禁运清单,增加了对俄罗斯个人和实体的制裁。俄军打击乌军指挥所 乌军击退俄军进攻</span></p>
+
+<p>&nbsp;</p>
+
+<p>&nbsp;</p>
+
+<p><span style="font-size:16px">俄罗斯国防部发言人科纳申科夫21日通报说,俄军在尼古拉耶夫和克拉玛托尔斯克打击了乌军多个指挥所,在顿涅茨克和尼古拉耶夫等地摧毁了多个乌军弹药库。另外,俄军还击落乌空军1架苏-25战机、1架米-8直升机和5架军用无人机。</span></p>
+
+<p>&nbsp;</p>
+
+<p>&nbsp;</p>
+
+<p><span style="font-size:16px">另据乌克兰国家通讯社21日援引乌各地军事部门的消息报道,俄军继续对苏梅、哈尔科夫、卢甘斯克、顿涅茨克等地区进行大规模炮击。在乌军阻击下,俄军未能在巴赫穆特方向取得突破,没有占领乌格列戈尔斯克发电厂。</span></p>
+
+<p>&nbsp;</p>
+
+<p>&nbsp;</p>
+
+<p><span style="font-size:16px">俄外长称在乌军事目标发生变化,与西方向乌军提供武器有关。</span></p>
+
+<p>&nbsp;</p>
+
+<p>&nbsp;</p>
+
+<p><span style="font-size:16px"><img alt="" src="/imgs/article-detail-pic-1.png" style="width:100%" /></span></p>
+
+<p>&nbsp;</p>
+
+<p><span style="font-size:16px">据央视新闻7月22日消息,俄罗斯国防部发言人科纳申科夫21日通报说,俄军在尼古拉耶夫和克拉玛托尔斯克打击了乌军多个指挥所。</span></p>
+
+<p>&nbsp;</p>
+
+<p>&nbsp;</p>
+
+<p><span style="font-size:16px">另据央视新闻报道称,当地时间21日,欧洲理事会公布了针对俄罗斯的新制裁措施,包括禁止进口来自俄罗斯金和珠宝;增加了俄罗斯可用于军用的物资和技术禁运清单,增加了对俄罗斯个人和实体的制裁。俄军打击乌军指挥所 乌军击退俄军进攻</span></p>
+
+<p>&nbsp;</p>
+
+<p>&nbsp;</p>
+
+<p><span style="font-size:16px">俄罗斯国防部发言人科纳申科夫21日通报说,俄军在尼古拉耶夫和克拉玛托尔斯克打击了乌军多个指挥所,在顿涅茨克和尼古拉耶夫等地摧毁了多个乌军弹药库。另外,俄军还击落乌空军1架苏-25战机、1架米-8直升机和5架军用无人机。</span></p>
+
+<p>&nbsp;</p>
+
+<p>&nbsp;</p>
+
+<p><span style="font-size:16px">另据乌克兰国家通讯社21日援引乌各地军事部门的消息报道,俄军继续对苏梅、哈尔科夫、卢甘斯克、顿涅茨克等地区进行大规模炮击。在乌军阻击下,俄军未能在巴赫穆特方向取得突破,没有占领乌格列戈尔斯克发电厂。</span></p>
+
+<p>&nbsp;</p>
+
+<p>&nbsp;</p>
+
+<p><span style="font-size:16px">俄外长称在乌军事目标发生变化,与西方向乌军提供武器有关。</span></p>
+
+<p>&nbsp;</p>
+
+<p>&nbsp;</p>
+
+<p><span style="font-size:16px">作者:香港特派员赵圆松;期刊:尖瑞科技期刊(ID:business-data)<br />
+本文由 @商业数据派 原创发布于人人都是产品经理,未经许可,禁止转载。<br />
+题图来自 Unsplash,基于CC0协议</span></p>
+<p>&nbsp;</p>
+
+<p>&nbsp;</p>
+`,
+    };
+  },
+};
+</script>
+
+<style>
+.detail .content {
+}
+.detail .action-button {
+  @apply !font-light border-1px !border-primary border-solid !text-primary ml-30px;
+}
+.detail .action-button.done {
+  @apply bg-primary !text-white;
+}
+.detail .el-textarea textarea {
+  @apply h-full bg-[#F7F7F7];
+}
+</style>

+ 115 - 0
src/pages/auth/change-password.vue

@@ -0,0 +1,115 @@
+<template>
+  <div
+    class="w-1200px ml-auto mr-auto mt-100px m-h-624px bg-white flex forget overflow-hidden mb-0"
+  >
+    <div class="w-700px h-full">
+      <img src="/imgs/login-banner.png" class="w-full object-cover" />
+    </div>
+
+    <div class="flex-1 flex justify-center">
+      <el-tabs v-model="activeName" class="w-410px mt-50px first">
+        <el-tab-pane class="tab-pane" :label="$t('修改密码')" name="first">
+          <div>
+            <ui-input class="h-60px !w-400px mb-24px" :placeholder="$t('请输入邮箱号码')">
+              <div slot="prefix" class="flex items-center h-full ml-20px">
+                <img slot="prefix" src="/imgs/email_icon.png" class="w-30px h-auto" />
+              </div>
+            </ui-input>
+            <ui-input class="h-60px !w-400px mb-24px" :placeholder="$t('请输入账号密码')">
+              <div slot="prefix" class="flex items-center h-full ml-20px">
+                <img src="/imgs/password_icon.png" class="w-30px h-auto" />
+              </div>
+              <div slot="suffix" class="flex items-center h-full mr-20px">
+                <img src="/imgs/eye_icon.png" class="w-30px h-auto" />
+                <!-- <img src="/imgs/eye_close_icon.png" class="w-30px h-auto" /> -->
+              </div>
+            </ui-input>
+            <ui-input
+              class="h-60px !w-400px mb-24px"
+              :placeholder="$t('请再次输入账号密码')"
+            >
+              <div slot="prefix" class="flex items-center h-full ml-20px">
+                <img src="/imgs/password_icon.png" class="w-30px h-auto" />
+              </div>
+              <div slot="suffix" class="flex items-center h-full mr-20px">
+                <img src="/imgs/eye_icon.png" class="w-30px h-auto" />
+                <!-- <img src="/imgs/eye_close_icon.png" class="w-30px h-auto" /> -->
+              </div>
+            </ui-input>
+            <ui-input
+              class="h-60px !w-400px mb-24px"
+              :placeholder="$t('请输入邮箱验证码')"
+            >
+              <div slot="prefix" class="flex items-center h-full ml-20px">
+                <img src="/imgs/vcode_icon.png" class="w-30px h-auto" />
+              </div>
+
+              <div slot="suffix" class="flex items-center h-full">
+                <el-button
+                  class="h-40px w-120px !text-size-14px !font-normal !px-0"
+                  type="primary"
+                  round
+                  >{{ $t("获取邮箱验证码") }}</el-button
+                >
+              </div>
+            </ui-input>
+
+            <div class="text-size-14px pl-30px mb-39px">
+              按下【完成注册】,即表示您同意<span class="text-primary cursor-pointer"
+                >用户注册协议</span
+              >
+            </div>
+            <el-button
+              class="h-60px w-400px !rounded-50px !text-size-24px !font-normal"
+              type="primary"
+              round
+              disabled
+              >{{ $t("完成注册") }}</el-button
+            >
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      activeName: "first",
+      loginType: "email",
+    };
+  },
+};
+</script>
+
+<style>
+.forget .el-input__inner {
+  background: #f7f7f7;
+  font-size: 16px;
+  padding-left: 60px !important;
+}
+.forget .tab-pane {
+  @apply flex flex-col items-center pt-10px;
+}
+.forget .el-tabs__nav {
+  @apply !w-full;
+}
+
+.forget
+  .first
+  > .el-tabs__header
+  > .el-tabs__nav-wrap
+  > .el-tabs__nav-scroll
+  > .el-tabs__nav
+  > .el-tabs__item {
+  @apply text-size-24px font-normal !w-full text-center !px-0;
+}
+.forget .el-tabs .el-tabs__item.is-active {
+  @apply !text-size-36px font-normal;
+}
+.forget .el-tabs .el-tabs__active-bar {
+  @apply !w-1/2 transform last:translate-x-1/2;
+}
+</style>

+ 191 - 0
src/pages/auth/login.vue

@@ -0,0 +1,191 @@
+<template>
+  <div
+    class="w-1200px ml-auto mr-auto mt-100px m-h-624px bg-white flex login overflow-hidden mb-0"
+  >
+    <div class="w-700px h-full">
+      <img src="/imgs/login-banner.png" class="w-full object-cover" />
+    </div>
+
+    <div class="flex-1 flex justify-center">
+      <el-tabs
+        v-model="activeName"
+        @tab-click="handleClick"
+        class="w-410px mt-50px first"
+      >
+        <el-tab-pane :label="$t('登录')" name="first" class="tab-pane">
+          <div
+            class="w-400px h-38px rounded-full border-[#E7E7E7] border-1px border-solid mb-24px flex"
+          >
+            <div
+              @click="loginType = 'email'"
+              :class="`custom-tab ${loginType === 'email' ? 'select' : ''}`"
+            >
+              {{ $t("邮箱验证登录") }}
+            </div>
+            <div
+              @click="loginType = 'account'"
+              :class="`custom-tab ${loginType === 'account' ? 'select' : ''}`"
+            >
+              {{ $t("账号密码登录") }}
+            </div>
+          </div>
+          <div v-if="loginType === 'email'">
+            <ui-input class="h-60px !w-400px mb-24px" :placeholder="$t('请输入邮箱号码')">
+              <div slot="prefix" class="flex items-center h-full ml-20px">
+                <img slot="prefix" src="/imgs/email_icon.png" class="w-30px h-auto" />
+              </div>
+            </ui-input>
+            <ui-input
+              class="h-60px !w-400px mb-58px"
+              :placeholder="$t('请输入邮箱验证码')"
+            >
+              <div slot="prefix" class="flex items-center h-full ml-20px">
+                <img src="/imgs/vcode_icon.png" class="w-30px h-auto" />
+              </div>
+
+              <div slot="suffix" class="flex items-center h-full">
+                <el-button
+                  class="h-40px w-120px !text-size-14px !font-normal !px-0"
+                  type="primary"
+                  round
+                  >{{ $t("获取邮箱验证码") }}</el-button
+                >
+              </div>
+            </ui-input>
+          </div>
+          <div v-if="loginType === 'account'" class="flex flex-col items-end">
+            <ui-input class="h-60px !w-400px mb-24px" :placeholder="$t('请输入账号')">
+              <div slot="prefix" class="flex items-center h-full ml-20px">
+                <img slot="prefix" src="/imgs/email_icon.png" class="w-30px h-auto" />
+              </div>
+            </ui-input>
+            <ui-input class="h-60px !w-400px mb-15px" :placeholder="$t('请输入账号密码')">
+              <div slot="prefix" class="flex items-center h-full ml-20px">
+                <img src="/imgs/password_icon.png" class="w-30px h-auto" />
+              </div>
+              <div slot="suffix" class="flex items-center h-full mr-20px">
+                <!-- <img src="/imgs/eye_icon.png" class="w-30px h-auto" /> -->
+                <img
+                  src="/imgs/eye_close_icon.png"
+                  class="w-30px h-auto cursor-pointer"
+                />
+              </div>
+            </ui-input>
+            <el-button
+              @click="$router.push('/change-pass')"
+              type="text"
+              class="!font-normal !mb-27px !p-0"
+            >
+              {{ $t("忘记密码") }}
+            </el-button>
+          </div>
+
+          <el-button
+            class="h-60px w-400px !rounded-50px !text-size-24px !font-normal"
+            type="primary"
+            round
+            >{{ $t("登录") }}</el-button
+          >
+        </el-tab-pane>
+        <el-tab-pane class="tab-pane" :label="$t('注册')" name="second">
+          <div>
+            <ui-input class="h-60px !w-400px mb-24px" :placeholder="$t('请输入昵称')">
+              <div slot="prefix" class="flex items-center h-full ml-20px">
+                <img slot="prefix" src="/imgs/user_icon.png" class="w-30px h-auto" />
+              </div>
+            </ui-input>
+            <ui-input class="h-60px !w-400px mb-24px" :placeholder="$t('请输入邮箱号码')">
+              <div slot="prefix" class="flex items-center h-full ml-20px">
+                <img slot="prefix" src="/imgs/email_icon.png" class="w-30px h-auto" />
+              </div>
+            </ui-input>
+            <ui-input
+              class="h-60px !w-400px mb-24px"
+              :placeholder="$t('请输入邮箱验证码')"
+            >
+              <div slot="prefix" class="flex items-center h-full ml-20px">
+                <img src="/imgs/vcode_icon.png" class="w-30px h-auto" />
+              </div>
+
+              <div slot="suffix" class="flex items-center h-full">
+                <el-button
+                  class="h-40px w-120px !text-size-14px !font-normal !px-0"
+                  type="primary"
+                  round
+                  >{{ $t("获取邮箱验证码") }}</el-button
+                >
+              </div>
+            </ui-input>
+            <ui-input class="h-60px !w-400px mb-15px" :placeholder="$t('请输入账号密码')">
+              <div slot="prefix" class="flex items-center h-full ml-20px">
+                <img src="/imgs/password_icon.png" class="w-30px h-auto" />
+              </div>
+              <div slot="suffix" class="flex items-center h-full mr-20px">
+                <img src="/imgs/eye_icon.png" class="w-30px h-auto" />
+                <!-- <img src="/imgs/eye_close_icon.png" class="w-30px h-auto" /> -->
+              </div>
+            </ui-input>
+
+            <el-button
+              class="h-60px w-400px !rounded-50px !text-size-24px !font-normal"
+              type="primary"
+              round
+              disabled
+              >{{ $t("确定") }}</el-button
+            >
+          </div>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      activeName: "first",
+      loginType: "email",
+    };
+  },
+};
+</script>
+
+<style>
+.login .el-input__inner {
+  background: #f7f7f7;
+  font-size: 16px;
+  padding-left: 60px !important;
+}
+.login .tab-pane {
+  @apply flex flex-col items-center pt-10px;
+}
+.login .el-tabs__nav {
+  @apply !w-full;
+}
+
+.login
+  .first
+  > .el-tabs__header
+  > .el-tabs__nav-wrap
+  > .el-tabs__nav-scroll
+  > .el-tabs__nav
+  > .el-tabs__item {
+  @apply text-size-24px font-normal !w-1/2 text-center !px-0;
+}
+.login .el-tabs .el-tabs__item.is-active {
+  @apply !text-size-36px font-normal;
+}
+.login .custom-tab {
+  @apply flex-1 flex justify-center items-center bg-[#F7F7F7] text-size-16px cursor-pointer;
+}
+.login .custom-tab.select {
+  @apply bg-white text-primary;
+}
+.login .custom-tab:first-child {
+  @apply border-r-1px border-solid border-r-[#E7E7E7] rounded-l-full;
+}
+.login .custom-tab:nth-child(2) {
+  @apply border-r-1px border-solid border-r-[#E7E7E7] rounded-r-full;
+}
+</style>

+ 87 - 0
src/pages/auth/profile-complete.vue

@@ -0,0 +1,87 @@
+<template>
+  <div class="w1200px bg-white mt-20px px-100px pb-100px">
+    <div class="h-33px"></div>
+    <ui-title-devider :title="$t('请设置个人相关信息后进入')"></ui-title-devider>
+    <div class="h-14px"></div>
+    <user-account-setting-info-item label="头像">
+      <div class="pl-20px">
+        <img src="imgs/avatar.png" class="w-80px h-80px" />
+      </div>
+    </user-account-setting-info-item>
+    <user-account-setting-info-item
+      label="昵称"
+      text="cyt"
+    ></user-account-setting-info-item>
+    <user-account-setting-info-item
+      label="账号"
+      text="15486323563@qq.com"
+    ></user-account-setting-info-item>
+    <user-account-setting-info-item label="密码">
+      <div class="pl-20px flex items-center">
+        <div v-if="!showPass" class="mr-50px">*********</div>
+        <div v-else class="mr-50px">1231asadas</div>
+        <div @click="showPass = !showPass">
+          <img
+            v-if="!showPass"
+            src="/imgs/eye_icon.png"
+            class="w-30px h-auto cursor-pointer"
+          />
+          <img
+            v-else
+            src="/imgs/eye_close_icon.png"
+            class="w-30px h-auto cursor-pointer"
+          />
+        </div>
+      </div>
+    </user-account-setting-info-item>
+    <user-account-setting-info-item :required="true" label="姓名">
+      <ui-input v-model="name" class="!w-345px"></ui-input>
+    </user-account-setting-info-item>
+    <user-account-setting-info-item :required="true" label="电话">
+      <ui-input v-model="phone" class="!w-345px">
+        <div slot="suffix" class="flex items-center h-full">
+          <div class="text-black">+86</div>
+          <div class="w-12px"></div>
+          <img src="/imgs/menu-arrow.png" class="w-6px h-auto" />
+          <div class="w-16px"></div>
+        </div> </ui-input
+    ></user-account-setting-info-item>
+    <user-account-setting-info-item :required="true" label="性别">
+      <el-radio-group v-model="gender">
+        <el-radio :label="0">女</el-radio>
+        <el-radio :label="1">男</el-radio>
+      </el-radio-group>
+    </user-account-setting-info-item>
+    <user-account-setting-info-item label="职业">
+      <ui-input v-model="job" class="!w-728px"></ui-input>
+    </user-account-setting-info-item>
+    <user-account-setting-info-item label="工作单位">
+      <ui-input v-model="jobUnit" class="!w-728px"></ui-input>
+    </user-account-setting-info-item>
+    <user-account-setting-info-item label="地址">
+      <ui-input v-model="addr" class="!w-728px"></ui-input>
+    </user-account-setting-info-item>
+    <div class="flex justify-center">
+      <el-button @click="$router.push('/home')" type="primary ">{{ $t("确定") }}</el-button>
+    </div>
+  </div>
+</template>
+
+<script>
+import {} from "element-ui";
+export default {
+  data() {
+    return {
+      gender: 0,
+      name: "陈小婷",
+      phone: "18926145678",
+      job: "产品经理",
+      jobUnit: "广州量子互联科技有限公司",
+      addr: "广州市黄埔区联和街道黄埔科学大道112号绿地广场1710室",
+      showPass: false,
+    };
+  },
+};
+</script>
+
+<style></style>

+ 1 - 1
src/pages/home/_components/home-tags.vue

@@ -16,7 +16,7 @@ export default {};
 </script>
 <style>
 .tag {
-  @apply text-primary h-24px text-size-14px font-normal rounded-100px min-w-75px px-10px bg-[#f7f7f7] flex items-center mr-30px mt-10px;
+  @apply text-primary h-24px text-size-14px font-normal rounded-100px min-w-75px px-10px bg-[#f7f7f7] flex items-center mr-30px mt-10px cursor-pointer;
 }
 .tag.selected {
   @apply bg-primary text-white;

+ 73 - 14
src/pages/home/home.vue

@@ -1,10 +1,25 @@
 <template>
-  <div>
+  <div class="w-1200px">
     <div class="h-20px"></div>
 
-    <ui-swiper :items="banner1" class="w-600px h-337px"></ui-swiper>
+    <div class="flex">
+      <div>
+        <ui-swiper
+          :showPagination="true"
+          :items="banner1"
+          class="w-600px h-337px"
+        ></ui-swiper>
+      </div>
+      <div class="w-10px"></div>
+      <div class="swiper-group">
+        <ui-swiper :items="banner1" titleClass="swiper-title" class="swiper"></ui-swiper>
+        <ui-swiper :items="banner1" titleClass="swiper-title" class="swiper"></ui-swiper>
+        <ui-swiper :items="banner1" titleClass="swiper-title" class="swiper"></ui-swiper>
+        <ui-swiper :items="banner1" titleClass="swiper-title" class="swiper"></ui-swiper>
+      </div>
+    </div>
     <div class="h-20px"></div>
-    <div class="w-1200px flex justify-between">
+    <div class="flex justify-between">
       <div class="left w-860px">
         <home-tags></home-tags>
         <div class="h-20px"></div>
@@ -26,11 +41,19 @@
               class="w-full h-3px absolute left-0 bottom-[-7.5px] bg-primary rounded-full"
             ></div>
           </div>
-
           <ui-devider></ui-devider>
           <div class="h-21px"></div>
+          <ui-swiper
+            class="mb-20px"
+            :items="[
+              { url: 'imgs/article_cover1.png', title: '这是标题' },
+              { url: 'imgs/article_cover1.png', title: '这是标题' },
+            ]"
+            titleClass="swiper-title"
+          ></ui-swiper>
+          <ui-devider></ui-devider>
 
-          <div v-for="item in 4" :key="item">
+          <div v-for="item in 9" :key="item">
             <ui-small-article></ui-small-article>
             <ui-devider></ui-devider>
           </div>
@@ -38,9 +61,12 @@
         <div class="h-20px"></div>
         <div class="px-20px bg-white">
           <div class="h-17px"></div>
-          <div class="relative inline-flex mb-6.5px">
-            <img src="/imgs/vip.png" class="w-24px h-auto mr-4px" />
-            <div class="font-thin text-[#000] text-size-20px">{{ $t("VIP期刊") }}</div>
+          <div class="relative flex mb-6.5px justify-between item-center">
+            <div class="inline-flex">
+              <img src="/imgs/vip.png" class="w-24px h-auto mr-4px" />
+              <div class="font-thin text-[#000] text-size-20px">{{ $t("VIP期刊") }}</div>
+            </div>
+            <el-button type="text" class="!p-0 !text-size-14px !font-normal !text-[#686868]">查看更多</el-button>
 
             <div
               class="w-full h-3px absolute left-0 bottom-[-7.5px] bg-primary rounded-full"
@@ -49,6 +75,23 @@
           <ui-devider></ui-devider>
           <div class="h-21px"></div>
 
+          <ui-swiper
+            class="mb-20px"
+            :items="[
+              { url: 'imgs/article_cover1.png', title: '这是标题' },
+              { url: 'imgs/article_cover1.png', title: '这是标题' },
+            ]"
+            titleClass="swiper-title"
+          ></ui-swiper>
+          <ui-swiper
+            class="mb-20px"
+            :items="[
+              { url: 'imgs/article_cover1.png', title: '这是标题' },
+              { url: 'imgs/article_cover1.png', title: '这是标题' },
+            ]"
+            titleClass="swiper-title"
+          ></ui-swiper>
+          <ui-devider></ui-devider>
           <div v-for="item in 4" :key="item">
             <ui-vip-article></ui-vip-article>
             <ui-devider></ui-devider>
@@ -64,14 +107,30 @@ export default {
   data() {
     return {
       banner1: [
-        { url: "/imgs/banner1.png" },
-        { url: "/imgs/banner1.png" },
-        { url: "/imgs/banner1.png" },
-        { url: "/imgs/banner1.png" },
-        { url: "/imgs/banner1.png" },
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
       ],
     };
   },
 };
 </script>
-<style></style>
+<style>
+.swiper-group {
+  display: grid;
+  grid-template-columns: repeat(2, 290px);
+  grid-template-rows: repeat(2, 163px);
+  grid-gap: 10px;
+}
+.swiper {
+  @apply w-290px;
+
+  /* align-items: end; */
+  /* @apply w-290px h-163px; */
+}
+.swiper-title {
+  @apply bottom-17px left-17px text-size-16px;
+}
+</style>

+ 142 - 0
src/pages/realtime-news/realtime-news.vue

@@ -0,0 +1,142 @@
+<template>
+  <div>
+    <ui-swiper
+      :showPagination="true"
+      :items="banner1"
+      class="w-screen h-350px"
+    ></ui-swiper>
+
+    <div class="w-1200px m-auto">
+      <div class="flex justify-between">
+        <div class="left w-860px">
+          <div class="h-20px"></div>
+          <div v-for="item in 5" :key="item">
+            <ui-main-article></ui-main-article>
+            <div class="h-20px"></div>
+          </div>
+          <ui-shadow-box class="w-full h-100px mb-20px">
+            <img src="/imgs/split-pic-1.png" class="w-full h-full object-cover" />
+          </ui-shadow-box>
+          <div v-for="item in 5" :key="item">
+            <ui-main-article></ui-main-article>
+            <div class="h-20px"></div>
+          </div>
+          <ui-shadow-box class="w-full h-100px mb-20px">
+            <img src="/imgs/split-pic-2.png" class="w-full h-full object-cover" />
+          </ui-shadow-box>
+          <div v-for="item in 5" :key="item">
+            <ui-main-article></ui-main-article>
+            <div class="h-20px"></div>
+          </div>
+        </div>
+        <div class="right w-320px">
+          <div class="px-20px bg-white">
+            <div class="h-17px"></div>
+            <div class="relative inline-flex mb-6.5px">
+              <img src="/imgs/hot.png" class="w-24px h-auto mr-4px" />
+              <div class="font-thin text-[#000] text-size-20px">{{ $t("热榜文章") }}</div>
+
+              <div
+                class="w-full h-3px absolute left-0 bottom-[-7.5px] bg-primary rounded-full"
+              ></div>
+            </div>
+            <ui-devider></ui-devider>
+            <div class="h-21px"></div>
+            <ui-swiper
+              class="mb-20px"
+              :items="[
+                { url: 'imgs/article_cover1.png', title: '这是标题' },
+                { url: 'imgs/article_cover1.png', title: '这是标题' },
+              ]"
+              titleClass="swiper-title"
+            ></ui-swiper>
+            <ui-devider></ui-devider>
+
+            <div v-for="item in 9" :key="item">
+              <ui-small-article></ui-small-article>
+              <ui-devider></ui-devider>
+            </div>
+          </div>
+          <div class="h-20px"></div>
+          <div class="px-20px bg-white">
+            <div class="h-17px"></div>
+            <div class="relative flex mb-6.5px justify-between item-center">
+              <div class="inline-flex">
+                <img src="/imgs/vip.png" class="w-24px h-auto mr-4px" />
+                <div class="font-thin text-[#000] text-size-20px">
+                  {{ $t("VIP期刊") }}
+                </div>
+              </div>
+              <el-button
+                type="text"
+                class="!p-0 !text-size-14px !font-normal !text-[#686868]"
+                >查看更多</el-button
+              >
+
+              <div
+                class="w-full h-3px absolute left-0 bottom-[-7.5px] bg-primary rounded-full"
+              ></div>
+            </div>
+            <ui-devider></ui-devider>
+            <div class="h-21px"></div>
+
+            <ui-swiper
+              class="mb-20px"
+              :items="[
+                { url: 'imgs/article_cover1.png', title: '这是标题' },
+                { url: 'imgs/article_cover1.png', title: '这是标题' },
+              ]"
+              titleClass="swiper-title"
+            ></ui-swiper>
+            <ui-swiper
+              class="mb-20px"
+              :items="[
+                { url: 'imgs/article_cover1.png', title: '这是标题' },
+                { url: 'imgs/article_cover1.png', title: '这是标题' },
+              ]"
+              titleClass="swiper-title"
+            ></ui-swiper>
+            <ui-devider></ui-devider>
+            <div v-for="item in 10" :key="item">
+              <ui-vip-article></ui-vip-article>
+              <ui-devider></ui-devider>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      banner1: [
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+      ],
+    };
+  },
+};
+</script>
+<style>
+.swiper-group {
+  display: grid;
+  grid-template-columns: repeat(2, 290px);
+  grid-template-rows: repeat(2, 163px);
+  grid-gap: 10px;
+}
+.swiper {
+  @apply w-290px;
+
+  /* align-items: end; */
+  /* @apply w-290px h-163px; */
+}
+.swiper-title {
+  @apply bottom-17px left-17px text-size-16px;
+}
+</style>

+ 142 - 0
src/pages/recommend/recommend.vue

@@ -0,0 +1,142 @@
+<template>
+  <div>
+    <ui-swiper
+      :showPagination="true"
+      :items="banner1"
+      class="w-screen h-350px"
+    ></ui-swiper>
+
+    <div class="w-1200px m-auto">
+      <div class="flex justify-between">
+        <div class="left w-860px">
+          <div class="h-20px"></div>
+          <div v-for="item in 5" :key="item">
+            <ui-main-article></ui-main-article>
+            <div class="h-20px"></div>
+          </div>
+          <ui-shadow-box class="w-full h-100px mb-20px">
+            <img src="/imgs/split-pic-1.png" class="w-full h-full object-cover" />
+          </ui-shadow-box>
+          <div v-for="item in 5" :key="item">
+            <ui-main-article></ui-main-article>
+            <div class="h-20px"></div>
+          </div>
+          <ui-shadow-box class="w-full h-100px mb-20px">
+            <img src="/imgs/split-pic-2.png" class="w-full h-full object-cover" />
+          </ui-shadow-box>
+          <div v-for="item in 5" :key="item">
+            <ui-main-article></ui-main-article>
+            <div class="h-20px"></div>
+          </div>
+        </div>
+        <div class="right w-320px">
+          <div class="px-20px bg-white">
+            <div class="h-17px"></div>
+            <div class="relative inline-flex mb-6.5px">
+              <img src="/imgs/hot.png" class="w-24px h-auto mr-4px" />
+              <div class="font-thin text-[#000] text-size-20px">{{ $t("热榜文章") }}</div>
+
+              <div
+                class="w-full h-3px absolute left-0 bottom-[-7.5px] bg-primary rounded-full"
+              ></div>
+            </div>
+            <ui-devider></ui-devider>
+            <div class="h-21px"></div>
+            <ui-swiper
+              class="mb-20px"
+              :items="[
+                { url: 'imgs/article_cover1.png', title: '这是标题' },
+                { url: 'imgs/article_cover1.png', title: '这是标题' },
+              ]"
+              titleClass="swiper-title"
+            ></ui-swiper>
+            <ui-devider></ui-devider>
+
+            <div v-for="item in 9" :key="item">
+              <ui-small-article></ui-small-article>
+              <ui-devider></ui-devider>
+            </div>
+          </div>
+          <div class="h-20px"></div>
+          <div class="px-20px bg-white">
+            <div class="h-17px"></div>
+            <div class="relative flex mb-6.5px justify-between item-center">
+              <div class="inline-flex">
+                <img src="/imgs/vip.png" class="w-24px h-auto mr-4px" />
+                <div class="font-thin text-[#000] text-size-20px">
+                  {{ $t("VIP期刊") }}
+                </div>
+              </div>
+              <el-button
+                type="text"
+                class="!p-0 !text-size-14px !font-normal !text-[#686868]"
+                >查看更多</el-button
+              >
+
+              <div
+                class="w-full h-3px absolute left-0 bottom-[-7.5px] bg-primary rounded-full"
+              ></div>
+            </div>
+            <ui-devider></ui-devider>
+            <div class="h-21px"></div>
+
+            <ui-swiper
+              class="mb-20px"
+              :items="[
+                { url: 'imgs/article_cover1.png', title: '这是标题' },
+                { url: 'imgs/article_cover1.png', title: '这是标题' },
+              ]"
+              titleClass="swiper-title"
+            ></ui-swiper>
+            <ui-swiper
+              class="mb-20px"
+              :items="[
+                { url: 'imgs/article_cover1.png', title: '这是标题' },
+                { url: 'imgs/article_cover1.png', title: '这是标题' },
+              ]"
+              titleClass="swiper-title"
+            ></ui-swiper>
+            <ui-devider></ui-devider>
+            <div v-for="item in 10" :key="item">
+              <ui-vip-article></ui-vip-article>
+              <ui-devider></ui-devider>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      banner1: [
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+        { url: "/imgs/banner1.png", title: "這裏是輪播圖推薦內容標題" },
+      ],
+    };
+  },
+};
+</script>
+<style>
+.swiper-group {
+  display: grid;
+  grid-template-columns: repeat(2, 290px);
+  grid-template-rows: repeat(2, 163px);
+  grid-gap: 10px;
+}
+.swiper {
+  @apply w-290px;
+
+  /* align-items: end; */
+  /* @apply w-290px h-163px; */
+}
+.swiper-title {
+  @apply bottom-17px left-17px text-size-16px;
+}
+</style>

+ 40 - 0
src/pages/user/_components/user-account-setting-info-item.vue

@@ -0,0 +1,40 @@
+<template>
+  <div class="info-item" v-bind="$attrs">
+    <div class="info-item-label">
+      <div class="content-holder">
+        <img
+          v-if="required"
+          src="/imgs/required_icon.png"
+          class="object-contain w-full h-full"
+        />
+      </div>
+      <div class="text-size-16px text-[#686868]">{{ $t(label) }}</div>
+    </div>
+    <div v-if="!$slots.default" class="text-size-16px text-black pl-20px">
+      {{ text }}
+    </div>
+    <slot></slot>
+  </div>
+</template>
+
+<script>
+export default {
+  props: {
+    label: {},
+    required: {},
+    text: {},
+  },
+};
+</script>
+
+<style>
+.info-item {
+  @apply flex mb-40px;
+}
+.info-item-label {
+  @apply flex w-120px items-center;
+}
+.info-item-label .content-holder {
+  @apply w-8px h-full  mr-6px ml-17px;
+}
+</style>

+ 71 - 0
src/pages/user/user-account-setting.vue

@@ -0,0 +1,71 @@
+<template>
+  <div class="account-setting">
+    <div class="h-27px"></div>
+    <ui-title-devider :title="$t('账号设置')"></ui-title-devider>
+    <div class="h-14px"></div>
+    <user-account-setting-info-item label="头像">
+      <div class="pl-20px">
+        <img src="imgs/avatar.png" class="w-80px h-80px" />
+      </div>
+    </user-account-setting-info-item>
+    <user-account-setting-info-item
+      label="昵称"
+      text="cyt"
+    ></user-account-setting-info-item>
+    <user-account-setting-info-item
+      label="账号"
+      text="15486323563@qq.com"
+    ></user-account-setting-info-item>
+    <user-account-setting-info-item label="密码">
+      <div class="pl-20px flex items-center">
+        <div class="mr-50px">*********</div>
+        <div class="text-primary cursor-pointer">重置密码</div>
+      </div>
+    </user-account-setting-info-item>
+    <user-account-setting-info-item :required="true" label="姓名">
+      <ui-input v-model="name" class="!w-345px"></ui-input>
+    </user-account-setting-info-item>
+    <user-account-setting-info-item :required="true" label="电话">
+      <ui-input v-model="phone" class="!w-345px">
+        <div slot="suffix" class="flex items-center h-full">
+          <div class="text-black">+86</div>
+          <div class="w-12px"></div>
+          <img src="/imgs/menu-arrow.png" class="w-6px h-auto" />
+          <div class="w-16px"></div>
+        </div> </ui-input
+    ></user-account-setting-info-item>
+    <user-account-setting-info-item  :required="true" label="性别">
+      <el-radio-group v-model="gender">
+        <el-radio :label="0">女</el-radio>
+        <el-radio :label="1">男</el-radio>
+      </el-radio-group>
+    </user-account-setting-info-item>
+    <user-account-setting-info-item label="职业">
+      <ui-input v-model="job" class="!w-728px"></ui-input>
+    </user-account-setting-info-item>
+    <user-account-setting-info-item label="工作单位">
+      <ui-input v-model="jobUnit" class="!w-728px"></ui-input>
+    </user-account-setting-info-item>
+    <user-account-setting-info-item label="地址">
+      <ui-input v-model="addr" class="!w-728px"></ui-input>
+    </user-account-setting-info-item>
+  </div>
+</template>
+
+<script>
+import {} from "element-ui";
+export default {
+    data(){
+        return {
+            gender: 0,
+            name: "陈小婷",
+            phone: "18926145678",
+            job: "产品经理",
+            jobUnit: "广州量子互联科技有限公司",
+            addr: "广州市黄埔区联和街道黄埔科学大道112号绿地广场1710室"
+        }
+    }
+};
+</script>
+
+<style></style>

+ 21 - 0
src/pages/user/user-collection.vue

@@ -0,0 +1,21 @@
+<template>
+  <div>
+    <div class="h-34px"></div>
+    <ui-title-devider title="我的收藏"></ui-title-devider>
+    <div class="px-40px">
+      <div class="h-20px"></div>
+      <ui-main-article class="mb-20px">
+        <!-- <img src="/imgs/star.png" slot="right" class="w-28px right-19px bottom-10px absolute"/> -->
+        <img src="/imgs/star-blank.png" slot="right" class="w-28px right-19px bottom-10px absolute"/>
+      </ui-main-article>
+      <ui-main-article class="mb-20px"></ui-main-article>
+      <ui-main-article class="mb-20px"></ui-main-article>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {};
+</script>
+
+<style lang="scss" scoped></style>

+ 20 - 0
src/pages/user/user-comment.vue

@@ -0,0 +1,20 @@
+<template>
+    <div>
+      <div class="h-34px"></div>
+      <ui-title-devider title="我的收藏"></ui-title-devider>
+      <div class="px-40px">
+        <div class="h-20px"></div>
+        <ui-main-article v-for="item in 4" class="mb-20px">
+          
+          
+        </ui-main-article>
+      </div>
+    </div>
+  </template>
+  
+  <script>
+  export default {};
+  </script>
+  
+  <style lang="scss" scoped></style>
+  

+ 20 - 0
src/pages/user/user-history.vue

@@ -0,0 +1,20 @@
+<template>
+    <div>
+      <div class="h-34px"></div>
+      <ui-title-devider title="我的收藏"></ui-title-devider>
+      <div class="px-40px">
+        <div class="h-20px"></div>
+        <ui-main-article v-for="item in 4" class="mb-20px">
+          
+          
+        </ui-main-article>
+      </div>
+    </div>
+  </template>
+  
+  <script>
+  export default {};
+  </script>
+  
+  <style lang="scss" scoped></style>
+  

+ 23 - 0
src/pages/user/user-like.vue

@@ -0,0 +1,23 @@
+<template>
+  <div>
+    <div class="h-34px"></div>
+    <ui-title-devider title="我的收藏"></ui-title-devider>
+    <div class="px-40px">
+      <div class="h-20px"></div>
+      <ui-main-article v-for="item in 4" class="mb-20px">
+        
+        <img
+          src="/imgs/like-button-checked.png"
+          slot="right"
+          class="w-28px right-19px bottom-10px absolute"
+        />
+      </ui-main-article>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {};
+</script>
+
+<style lang="scss" scoped></style>

+ 146 - 0
src/pages/user/user-order.vue

@@ -0,0 +1,146 @@
+<template>
+  <div>
+    <div class="h-34px"></div>
+    <ui-title-devider :showBorder="false" title="我的订单"></ui-title-devider>
+    <div class="pl-27px">
+      <el-tabs v-model="activeName" @tab-click="handleClick">
+        <el-tab-pane label="会员订单" name="first">
+          <ui-order-table :data="vipOrdersData" :columns="vipOrders"></ui-order-table>
+        </el-tab-pane>
+        <el-tab-pane label="商品订单" name="second">
+          <ui-order-table :data="goodsOrdersData" :columns="goodsOrders">
+            <template v-slot:0="{ row }">
+              <img class="w-full h-full object-contain" :src="row.pic" />
+            </template>
+          </ui-order-table>
+        </el-tab-pane>
+      </el-tabs>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      activeName: "first",
+      vipOrdersData: [
+        {
+          name: "杨贵妃",
+          time: "30(天)",
+          price: "¥99",
+          status: "已支付",
+          payType: "微信",
+        },
+        {
+          name: "杨贵妃",
+          time: "30(天)",
+          price: "¥99",
+          status: "已支付",
+          payType: "微信",
+        },
+      ],
+      vipOrders: [
+        {
+          prop: "name",
+          label: "会员名称",
+          align: "center",
+        },
+        {
+          prop: "time",
+          label: "时长/(天)",
+          align: "center",
+        },
+        {
+          prop: "price",
+          label: "实付金额",
+          align: "center",
+        },
+        {
+          prop: "status",
+          label: "交易状态",
+          align: "center",
+        },
+        {
+          prop: "payType",
+          label: "支付方式",
+          align: "center",
+        },
+      ],
+      goodsOrdersData: [
+        {
+          pic: "/imgs/article_cover_small1.png",
+          name: "这是产品名",
+          addressInfo: "xxxxx",
+          count: "99",
+          price: "¥99",
+          status: "已交易",
+          payType: "微信",
+        },
+        {
+          pic: "/imgs/article_cover_small1.png",
+          name: "这是产品名",
+          addressInfo: "xxxxx",
+          count: "99",
+          price: "¥99",
+          status: "已交易",
+          payType: "微信",
+        },
+        {
+          pic: "/imgs/article_cover_small1.png",
+          name: "这是产品名",
+          addressInfo: "xxxxx",
+          count: "99",
+          price: "¥99",
+          status: "已交易",
+          payType: "微信",
+        }
+      ],
+      goodsOrders: [
+        {
+          prop: "pic",
+          label: "产品图",
+          align: "center",
+          width: "88px",
+        },
+        {
+          prop: "name",
+          label: "产品名",
+          align: "center",
+        },
+        {
+          prop: "addressInfo",
+          label: "收货信息",
+          align: "center",
+        },
+        {
+          prop: "count",
+          label: "数量",
+          align: "center",
+        },
+        {
+          prop: "price",
+          label: "实付金额",
+          align: "center",
+        },
+        {
+          prop: "status",
+          label: "交易状态",
+          align: "center",
+        },
+        {
+          prop: "payType",
+          label: "支付方式",
+          align: "center",
+        },
+      ],
+    };
+  },
+};
+</script>
+
+<style>
+.header {
+  @apply bg-primary;
+}
+</style>

+ 68 - 0
src/pages/user/user-personal-center.vue

@@ -0,0 +1,68 @@
+<template>
+  <div class="personal">
+    <div class="h-34px"></div>
+    <ui-title-devider title="个人信息"></ui-title-devider>
+    <div class="h-22.5px"></div>
+    <div class="flex flex-wrap items-center pl-40px">
+      <div class="info-item">
+        <div class="info-item-label">头像:</div>
+        <img class="w-80px h-80px rounded-full" src="/imgs/avatar.png" />
+      </div>
+      <div class="info-item">
+        <div class="info-item-label">昵称:</div>
+        <div class="text-size-16px text-black mr-20px">cyt</div>
+      </div>
+      <div class="info-item">
+        <div class="info-item-label">账号:</div>
+        <div class="text-size-16px text-black mr-20px">15486323563@qq.com</div>
+      </div>
+      <div class="info-item">
+        <div class="info-item-label">密码:</div>
+        <div class="text-size-16px text-black mr-20px">15486323563@qq.com</div>
+      </div>
+      <div class="info-item">
+        <div class="info-item-label">姓名:</div>
+        <div class="text-size-16px text-black mr-20px">陈小婷</div>
+      </div>
+      <div class="info-item">
+        <div class="info-item-label">电话:</div>
+        <div class="text-size-16px text-black mr-20px">18926171456</div>
+      </div>
+      <div class="info-item">
+        <div class="info-item-label">性别:</div>
+        <div class="text-size-16px text-black mr-20px">女</div>
+      </div>
+      <div class="info-item">
+        <div class="info-item-label">职业:</div>
+        <div class="text-size-16px text-black mr-20px">产品经理</div>
+      </div>
+      <div class="info-item">
+        <div class="info-item-label">工作单位:</div>
+        <div class="text-size-16px text-black mr-20px">广州量子互联科技有限公司</div>
+      </div>
+      <div class="!w-full info-item">
+        <div class="info-item-label">地址:</div>
+        <div class="text-size-16px text-black mr-20px">
+          广州市黄埔区联和街道黄埔科学大道112号绿地广场1710室
+        </div>
+      </div>
+    </div>
+    <ui-title-devider title="会员服务"></ui-title-devider>
+    <div class="h-26px"></div>
+    <div class="flex justify-around">
+      <ui-vip-preset></ui-vip-preset>
+      <ui-vip-preset></ui-vip-preset>
+      <ui-vip-preset></ui-vip-preset>
+    </div>
+    <div class="h-111px"></div>
+  </div>
+</template>
+
+<style scoped>
+.info-item {
+  @apply flex w-1/2 items-center mb-33px;
+}
+.info-item-label {
+  @apply text-size-16px text-[#686868] mr-20px whitespace-nowrap;
+}
+</style>

+ 26 - 0
src/pages/user/user-subscription.vue

@@ -0,0 +1,26 @@
+<template>
+  <div>
+    <div class="h-34px"></div>
+    <ui-title-devider title="我的收藏"></ui-title-devider>
+    <div class="px-40px">
+      <div class="h-20px"></div>
+      <ui-main-article v-for="item in 4" class="mb-20px">
+        <!-- <div slot="right" class="w-100px h-30px rounded-full flex items-center justify-center text-white text-size-14 bg-primary absolute right-26px bottom-12px">
+            {{$t("取消订阅")}}
+          </div> -->
+        <div
+          slot="right"
+          class="w-100px h-30px rounded-full flex items-center justify-center text-primary text-size-14 border-primary absolute right-26px bottom-12px border-1px border-solid"
+        >
+          {{ $t("取消订阅") }}
+        </div>
+      </ui-main-article>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {};
+</script>
+
+<style lang="scss" scoped></style>

+ 44 - 1
src/router/index.ts

@@ -2,7 +2,22 @@ import Vue from "vue";
 import type { RouteConfig } from "vue-router";
 import VueRouter from "vue-router";
 import Home from "@/pages/home/home.vue";
+import Recommend from "@/pages/recommend/recommend.vue";
+import RealtimeNews from "@/pages/realtime-news/realtime-news.vue";
+import ArticleDetail from "@/pages/article-detail/article-detail.vue";
 import BasicLayout from "@/components/layout-basic/layout-basic.vue";
+import UserLayout from "@/components/layout-user/layout-user.vue";
+import UserPersonalCenter from "@/pages/user/user-personal-center.vue";
+import UserAccountSetting from "@/pages/user/user-account-setting.vue";
+import UserOrder from "@/pages/user/user-order.vue";
+import Like from "@/pages/user/user-like.vue";
+import Comment from "@/pages/user/user-comment.vue";
+import Collection from "@/pages/user/user-collection.vue";
+import History from "@/pages/user/user-history.vue";
+import Subscription from "@/pages/user/user-subscription.vue";
+import Login from "@/pages/auth/login.vue";
+import ChangePass from "@/pages/auth/change-password.vue";
+import ProfileComplete from "@/pages/auth/profile-complete.vue";
 
 Vue.use(VueRouter);
 
@@ -13,10 +28,38 @@ export const routes: RouteConfig[] = [
     // NOTE: you can also apply meta information
     // meta: {authRequired: false }
     component: BasicLayout,
-    children: [{ path: "/home", component: Home }],
+    children: [
+      { path: "/login", component: Login },
+      { path: "/home", component: Home },
+      { path: "/recommend", component: Recommend },
+      { path: "/realtime-news", component: RealtimeNews },
+      { path: "/change-pass", component: ChangePass },
+      { path: "/profile-complete", component: ProfileComplete },
+      { path: "/article-detail", component: ArticleDetail },
+      {
+        path: "/user",
+        name: "user",
+        // NOTE: you can also apply meta information
+        // meta: {authRequired: false }
+        component: UserLayout,
+        children: [
+          { path: "personal-center", component: UserPersonalCenter },
+          { path: "account-setting", component: UserAccountSetting },
+          { path: "order", component: UserOrder },
+          { path: "collection", component: Collection },
+          { path: "subscription", component: Subscription },
+          { path: "like", component: Like },
+          { path: "comment", component: Comment },
+          { path: "history", component: History },
+        ],
+        // NOTE: you can also lazy-load the component
+        // component: () => import("@/views/About.vue")
+      },
+    ],
     // NOTE: you can also lazy-load the component
     // component: () => import("@/views/About.vue")
   },
+
   {
     path: "/:path(.*)",
     name: "NotFound",

+ 3 - 3
tailwind.config.js

@@ -3,9 +3,9 @@ module.exports = {
   theme: {
     extend: {
       colors: {
-        'primary': '#124026',
-      }
-    }
+        primary: "#124026",
+      },
+    },
   },
   variants: {
     theme: {},

+ 20 - 20
vite.config.ts

@@ -1,16 +1,17 @@
-import path from 'path'
-import { defineConfig } from 'vite'
-import vue from '@vitejs/plugin-vue2'
-import WindiCSS from 'vite-plugin-windicss'
-import Components from 'unplugin-vue-components/vite'
-import Icons from 'unplugin-icons/vite'
-import IconsResolver from 'unplugin-icons/resolver'
-import AutoImport from 'unplugin-auto-import/vite'
+import path from "path";
+import { defineConfig } from "vite";
+import vue from "@vitejs/plugin-vue2";
+import WindiCSS from "vite-plugin-windicss";
+import Components from "unplugin-vue-components/vite";
+import { ElementUiResolver } from "unplugin-vue-components/resolvers";
+import Icons from "unplugin-icons/vite";
+import IconsResolver from "unplugin-icons/resolver";
+import AutoImport from "unplugin-auto-import/vite";
 
 const config = defineConfig({
   resolve: {
     alias: {
-      '@': `${path.resolve(__dirname, 'src')}`,
+      "@": `${path.resolve(__dirname, "src")}`,
     },
   },
 
@@ -22,26 +23,25 @@ const config = defineConfig({
     vue(),
     WindiCSS(),
     Components({
-      dirs:['src/components','src/pages/**/_components'],
+      dirs: ["src/components", "src/pages/**/_components"],
       resolvers: [
-        IconsResolver({
-          componentPrefix: '',
-        }),
+        // IconsResolver({
+        //   componentPrefix: "",
+        // }),
+        ElementUiResolver({}),
       ],
-      dts: 'src/components.d.ts',
+      dts: "src/components.d.ts",
     }),
     Icons(),
     AutoImport({
-      imports: [
-        '@vueuse/core',
-      ],
-      dts: 'src/auto-imports.d.ts',
+      imports: ["@vueuse/core"],
+      dts: "src/auto-imports.d.ts",
     }),
   ],
 
   server: {
     port: 3333,
   },
-})
+});
 
-export default config
+export default config;

+ 72 - 0
yarn.lock

@@ -446,6 +446,26 @@ array.prototype.flatmap@^1.3.0:
     es-abstract "^1.19.2"
     es-shim-unscopables "^1.0.0"
 
+async-validator@~1.8.1:
+  version "1.8.5"
+  resolved "https://registry.npmmirror.com/async-validator/-/async-validator-1.8.5.tgz#dc3e08ec1fd0dddb67e60842f02c0cd1cec6d7f0"
+  integrity sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==
+  dependencies:
+    babel-runtime "6.x"
+
+babel-helper-vue-jsx-merge-props@^2.0.0:
+  version "2.0.3"
+  resolved "https://registry.npmmirror.com/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz#22aebd3b33902328e513293a8e4992b384f9f1b6"
+  integrity sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==
+
+babel-runtime@6.x:
+  version "6.26.0"
+  resolved "https://registry.npmmirror.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
+  integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==
+  dependencies:
+    core-js "^2.4.0"
+    regenerator-runtime "^0.11.0"
+
 balanced-match@^1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
@@ -596,6 +616,11 @@ concat-map@0.0.1:
   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
   integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
 
+core-js@^2.4.0:
+  version "2.6.12"
+  resolved "https://registry.npmmirror.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
+  integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
+
 core-js@^3.24.0:
   version "3.24.0"
   resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.24.0.tgz#4928d4e99c593a234eb1a1f9abd3122b04d3ac57"
@@ -651,6 +676,11 @@ deep-is@^0.1.3:
   resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
   integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
 
+deepmerge@^1.2.0:
+  version "1.5.2"
+  resolved "https://registry.npmmirror.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753"
+  integrity sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==
+
 define-properties@^1.1.3, define-properties@^1.1.4:
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1"
@@ -689,6 +719,11 @@ dom-serializer@^1.0.1:
     domhandler "^4.2.0"
     entities "^2.0.0"
 
+dom-to-image@^2.6.0:
+  version "2.6.0"
+  resolved "https://registry.npmmirror.com/dom-to-image/-/dom-to-image-2.6.0.tgz#8a503608088c87b1c22f9034ae032e1898955867"
+  integrity sha512-Dt0QdaHmLpjURjU7Tnu3AgYSF2LuOmksSGsUcE6ItvJoCWTBEmiMXcqBdNSAm9+QbbwD7JMoVsuuKX6ZVQv1qA==
+
 dom7@^3.0.0:
   version "3.0.0"
   resolved "https://registry.npmmirror.com/dom7/-/dom7-3.0.0.tgz#b861ce5d67a6becd7aaa3ad02942ff14b1240331"
@@ -717,6 +752,18 @@ domutils@^2.8.0:
     domelementtype "^2.2.0"
     domhandler "^4.2.0"
 
+element-ui@^2.15.10:
+  version "2.15.10"
+  resolved "https://registry.npmmirror.com/element-ui/-/element-ui-2.15.10.tgz#fde0ff5cb4c30e8eb166d617f85916defe5948f1"
+  integrity sha512-jmD++mU2wKXbisvx4fxOl2mHaU+HWHTAq/3Wf8x9Bwyu4GdDZPLABb+CGi3DWN6fPqdgRcd74aX39DO+YHObLw==
+  dependencies:
+    async-validator "~1.8.1"
+    babel-helper-vue-jsx-merge-props "^2.0.0"
+    deepmerge "^1.2.0"
+    normalize-wheel "^1.0.1"
+    resize-observer-polyfill "^1.5.0"
+    throttle-debounce "^1.0.1"
+
 entities@^2.0.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
@@ -1267,6 +1314,11 @@ file-entry-cache@^6.0.1:
   dependencies:
     flat-cache "^3.0.4"
 
+file-saver@^2.0.5:
+  version "2.0.5"
+  resolved "https://registry.npmmirror.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38"
+  integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==
+
 fill-range@^7.0.1:
   version "7.0.1"
   resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
@@ -1959,6 +2011,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
   resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
   integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
 
+normalize-wheel@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.npmmirror.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz#aec886affdb045070d856447df62ecf86146ec45"
+  integrity sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==
+
 npm-run-path@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
@@ -2286,6 +2343,11 @@ readdirp@~3.6.0:
   dependencies:
     picomatch "^2.2.1"
 
+regenerator-runtime@^0.11.0:
+  version "0.11.1"
+  resolved "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
+  integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
+
 regexp-tree@^0.1.24, regexp-tree@~0.1.1:
   version "0.1.24"
   resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.24.tgz#3d6fa238450a4d66e5bc9c4c14bb720e2196829d"
@@ -2305,6 +2367,11 @@ regexpp@^3.0.0, regexpp@^3.2.0:
   resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
   integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
 
+resize-observer-polyfill@^1.5.0:
+  version "1.5.1"
+  resolved "https://registry.npmmirror.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
+  integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
+
 resolve-from@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
@@ -2569,6 +2636,11 @@ text-table@^0.2.0:
   resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
   integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
 
+throttle-debounce@^1.0.1:
+  version "1.1.0"
+  resolved "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-1.1.0.tgz#51853da37be68a155cb6e827b3514a3c422e89cd"
+  integrity sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg==
+
 to-regex-range@^5.0.1:
   version "5.0.1"
   resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"