Lechan Dai 2 năm trước cách đây
commit
a94a3d77b5
60 tập tin đã thay đổi với 4441 bổ sung0 xóa
  1. 3 0
      .env
  2. 4 0
      .eslintignore
  3. 3 0
      .eslintrc.js
  4. 289 0
      .gitignore
  5. 4 0
      .husky/pre-commit
  6. 1 0
      .nvmrc
  7. 6 0
      .vscode/settings.json
  8. 21 0
      LICENSE
  9. 80 0
      README.md
  10. 14 0
      index.html
  11. 38 0
      package.json
  12. BIN
      public/imgs/article_cover1.png
  13. BIN
      public/imgs/article_cover_small1.png
  14. BIN
      public/imgs/banner1.png
  15. BIN
      public/imgs/cover-tag.png
  16. BIN
      public/imgs/down.png
  17. BIN
      public/imgs/favicon.ico
  18. BIN
      public/imgs/hot.png
  19. BIN
      public/imgs/new.png
  20. BIN
      public/imgs/search.png
  21. BIN
      public/imgs/time.png
  22. BIN
      public/imgs/tougao.png
  23. BIN
      public/imgs/vip-cover1.png
  24. BIN
      public/imgs/vip.png
  25. 6 0
      src/App.vue
  26. 1 0
      src/assets/not-found.svg
  27. 15 0
      src/assets/vite-logo.svg
  28. 2 0
      src/assets/vue-logo.svg
  29. 203 0
      src/auto-imports.d.ts
  30. 38 0
      src/components.d.ts
  31. 31 0
      src/components/Feature.vue
  32. 54 0
      src/components/Features.vue
  33. 25 0
      src/components/Hero.vue
  34. 69 0
      src/components/Navbar.vue
  35. 14 0
      src/components/layout-basic/layout-basic.vue
  36. 7 0
      src/components/shared/ButtonPrimary.vue
  37. 7 0
      src/components/shared/ButtonSecondary.vue
  38. 7 0
      src/components/shared/Heading1.vue
  39. 7 0
      src/components/shared/Heading2.vue
  40. 15 0
      src/components/ui-devider/ui-devider.vue
  41. 37 0
      src/components/ui-main-article/ui-main-article.vue
  42. 65 0
      src/components/ui-nav-bar/ui-nav-bar.vue
  43. 24 0
      src/components/ui-portal/ui-portal.vue
  44. 12 0
      src/components/ui-shadow-box/ui-shadow-box.vue
  45. 29 0
      src/components/ui-small-article/ui-small-article.vue
  46. 81 0
      src/components/ui-swiper/ui-swiper.vue
  47. 22 0
      src/components/ui-vip-article/ui-vip-article.vue
  48. 12 0
      src/locales/zh-CN.js
  49. 3 0
      src/locales/zh-TW.js
  50. 30 0
      src/main.js
  51. 7 0
      src/pages/home/_components/home-new.vue
  52. 24 0
      src/pages/home/_components/home-tags.vue
  53. 77 0
      src/pages/home/home.vue
  54. 33 0
      src/router/index.ts
  55. 15 0
      src/shims-tsx.d.ts
  56. 4 0
      src/shims-vue.d.ts
  57. 14 0
      tailwind.config.js
  58. 43 0
      tsconfig.json
  59. 47 0
      vite.config.ts
  60. 2898 0
      yarn.lock

+ 3 - 0
.env

@@ -0,0 +1,3 @@
+NODE_ENV=production
+
+VITE_APP_NAME=Application

+ 4 - 0
.eslintignore

@@ -0,0 +1,4 @@
+dist
+public
+src
+/

+ 3 - 0
.eslintrc.js

@@ -0,0 +1,3 @@
+module.exports = {
+  // extends: '@antfu',
+}

+ 289 - 0
.gitignore

@@ -0,0 +1,289 @@
+# Created by https://www.toptal.com/developers/gitignore/api/vue,node,macos,windows,linux,vscode,intellij+all
+# Edit at https://www.toptal.com/developers/gitignore?templates=vue,node,macos,windows,linux,vscode,intellij+all
+
+### Intellij+all ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn.  Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### Intellij+all Patch ###
+# Ignores the whole .idea folder and all .iml files
+# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
+
+.idea/
+
+# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
+
+*.iml
+modules.xml
+.idea/misc.xml
+*.ipr
+
+# Sonarlint plugin
+.idea/sonarlint
+
+### Linux ###
+*~
+
+# temporary files which can be created if a process still has a handle open of a deleted file
+.fuse_hidden*
+
+# KDE directory preferences
+.directory
+
+# Linux trash folder which might appear on any partition or disk
+.Trash-*
+
+# .nfs files are created when an open file is removed but is still being accessed
+.nfs*
+
+### macOS ###
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+### Node ###
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+lerna-debug.log*
+
+# Diagnostic reports (https://nodejs.org/api/report.html)
+report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
+
+# Runtime data
+pids
+*.pid
+*.seed
+*.pid.lock
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+*.lcov
+
+# nyc test coverage
+.nyc_output
+
+# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# Bower dependency directory (https://bower.io/)
+bower_components
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (https://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directories
+node_modules/
+jspm_packages/
+
+# TypeScript v1 declaration files
+typings/
+
+# TypeScript cache
+*.tsbuildinfo
+
+# Optional npm cache directory
+.npm
+
+# Optional eslint cache
+.eslintcache
+
+# Optional stylelint cache
+.stylelintcache
+
+# Microbundle cache
+.rpt2_cache/
+.rts2_cache_cjs/
+.rts2_cache_es/
+.rts2_cache_umd/
+
+# Optional REPL history
+.node_repl_history
+
+# Output of 'npm pack'
+*.tgz
+
+# Yarn Integrity file
+.yarn-integrity
+
+# dotenv environment variables file
+.env.test
+.env*.local
+
+# parcel-bundler cache (https://parceljs.org/)
+.cache
+.parcel-cache
+
+# Next.js build output
+.next
+
+# Nuxt.js build / generate output
+.nuxt
+dist
+
+# Gatsby files
+.cache/
+# Comment in the public line in if your project uses Gatsby and not Next.js
+# https://nextjs.org/blog/next-9-1#public-directory-support
+# public
+
+# vuepress build output
+.vuepress/dist
+
+# Serverless directories
+.serverless/
+
+# FuseBox cache
+.fusebox/
+
+# DynamoDB Local files
+.dynamodb/
+
+# TernJS port file
+.tern-port
+
+# Stores VSCode versions used for testing VSCode extensions
+.vscode-test
+
+### vscode ###
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+### Vue ###
+# gitignore template for Vue.js projects
+#
+# Recommended template: Node.gitignore
+
+### Windows ###
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# End of https://www.toptal.com/developers/gitignore/api/vue,node,macos,windows,linux,vscode,intellij+all

+ 4 - 0
.husky/pre-commit

@@ -0,0 +1,4 @@
+#!/bin/sh
+. "$(dirname "$0")/_/husky.sh"
+
+yarn lint

+ 1 - 0
.nvmrc

@@ -0,0 +1 @@
+16

+ 6 - 0
.vscode/settings.json

@@ -0,0 +1,6 @@
+{
+    "tailwindCSS.includeLanguages": {
+        "vue": "html",
+        "vue-html": "html"
+    }
+}

+ 21 - 0
LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 lstoeferle
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 80 - 0
README.md

@@ -0,0 +1,80 @@
+<h1 align="center">Vite ⚡ - Vue 2 starter template</h1>
+
+<p align="center">
+  Create a Vue 2 application bundled by the lightning fast build tool <a href="https://github.com/vitejs/vite">Vite</a>
+</p>
+
+<p align="center">
+ <a href="https://vite-vue2-starter.netlify.app"> ✨ Live Demo</a>
+</p>
+
+## Features
+
+* ⚡️ [Vite](https://github.com/vitejs/vite), [Vue 2](https://github.com/vuejs/vue) - lightning fast
+* 📦 [Components auto importing](https://github.com/antfu/unplugin-vue-components)
+* 📥 [APIs auto importing](https://github.com/antfu/unplugin-auto-import) - use Composition API and others directly
+* 🚦 [Vue-Router](https://github.com/vuejs/vue-router)
+* 🎨 [Windi CSS](https://github.com/windicss/vite-plugin-windicss) - next generation utility-first CSS framework
+* 😃 [Use icons from any icon sets, with no compromise](https://github.com/antfu/unplugin-icons)
+* 🧰 [VueUse](https://github.com/vueuse/vueuse) - Collection of essential Vue Composition Utilities
+* 🦾 Typescript, of course
+
+## Vite plugins
+
+* [`@vitejs/plugin-vue2`](https://github.com/vitejs/vite-plugin-vue2) -
+  Vue 2 support for Vite
+* [`unplugin-vue-components`](https://github.com/antfu/unplugin-vue-components) -
+  importing Vue components on-demand
+* [`unplugin-auto-import`](https://github.com/antfu/unplugin-auto-import) -
+  importing APIs like CompositionAPI on-demand
+* [`vite-plugin-windicss`](https://github.com/windicss/vite-plugin-windicss) -
+  easy WindiCSS integration
+* [`unplugin-icons`](https://github.com/antfu/unplugin-icons) -
+  importing icons as Vue components on-demand
+
+
+## Try it now!
+
+### GitHub Template
+
+[Create a repo from this template on GitHub](https://github.com/lstoeferle/vite-vue2-windicss-starter/generate)
+
+### Clone
+
+If you prefer to do it manually with a cleaner git history
+
+```bash
+npx degit lstoeferle/vite-vue2-windicss-starter my-vite-vue2-app
+cd my-vite-vue2-app
+yarn install
+```
+
+## Usage
+
+### Development
+
+Just run and visit [http://localhost:3333](http://localhost:3333)
+
+```bash
+yarn dev
+```
+
+### Build
+
+To build the App, run
+
+```bash
+yarn build
+```
+
+And you will see the generated files in `dist`, which are ready to be served.
+
+## Why
+
+Vue 3 is awesome, but we should not forget about supporting Vue 2 ♥️
+
+### Credits
+
+This project is inspired by [Vitesse](https://github.com/antfu/vitesse), an opinionated Vite starter template for Vue 3.
+
+Big thanks to [Anthony Fu](https://github.com/antfu) for the inspiration and all the amazing tools you create.

+ 14 - 0
index.html

@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+      <meta charset="utf-8">
+      <meta http-equiv="X-UA-Compatible" content="IE=edge">
+      <meta name="viewport" content="width=device-width,initial-scale=1.0">
+      <link rel="icon" href="/favicon.ico">
+      <title>Example</title>
+  </head>
+  <body >
+    <div id="app"></div>
+    <script type="module" src="/src/main.js"></script>
+  </body>
+</html>

+ 38 - 0
package.json

@@ -0,0 +1,38 @@
+{
+  "private": true,
+  "scripts": {
+    "postinstall": "husky install",
+    "dev": "vite",
+    "build": "vite build",
+    "lint": "eslint \"**/*.{vue,ts,js}\"",
+    "lint:fix": "eslint \"**/*.{vue,ts,js}\" --fix"
+  },
+  "dependencies": {
+    "@vueuse/core": "^9.0.0",
+    "core-js": "^3.24.0",
+    "nanoid": "^4.0.0",
+    "portal-vue": "^2.1.7",
+    "swiper": "6.x",
+    "vue": "^2.7.8",
+    "vue-awesome-swiper": "4.1.1",
+    "vue-i18n": "8",
+    "vue-router": "^3.5.4"
+  },
+  "devDependencies": {
+    "@antfu/eslint-config": "^0.25.2",
+    "@iconify/json": "^2.1.83",
+    "@vitejs/plugin-vue2": "^1.1.2",
+    "eslint": "^8.20.0",
+    "husky": "^8.0.1",
+    "sass": "^1.55.0",
+    "typescript": "^4.7.4",
+    "unplugin-auto-import": "^0.10.1",
+    "unplugin-icons": "^0.14.7",
+    "unplugin-vue-components": "^0.21.2",
+    "vite": "^3.0.3",
+    "vite-plugin-windicss": "^1.8.7",
+    "vue-template-compiler": "^2.7.8",
+    "vue-template-es2015-compiler": "^1.9.1",
+    "windicss": "^3.5.6"
+  }
+}

BIN
public/imgs/article_cover1.png


BIN
public/imgs/article_cover_small1.png


BIN
public/imgs/banner1.png


BIN
public/imgs/cover-tag.png


BIN
public/imgs/down.png


BIN
public/imgs/favicon.ico


BIN
public/imgs/hot.png


BIN
public/imgs/new.png


BIN
public/imgs/search.png


BIN
public/imgs/time.png


BIN
public/imgs/tougao.png


BIN
public/imgs/vip-cover1.png


BIN
public/imgs/vip.png


+ 6 - 0
src/App.vue

@@ -0,0 +1,6 @@
+<template>
+  <div id="app" class="bg-[#F7F7F7]">
+    
+      <RouterView />
+  </div>
+</template>

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
src/assets/not-found.svg


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 15 - 0
src/assets/vite-logo.svg


+ 2 - 0
src/assets/vue-logo.svg

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg version="1.1" viewBox="0 0 261.76 226.69" xmlns="http://www.w3.org/2000/svg"><g transform="matrix(1.3333 0 0 -1.3333 -76.311 313.34)"><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-75.491l98.16-170.02 98.16 170.02z" fill="#41b883"/></g><g transform="translate(178.06 235.01)"><path d="m0 0-22.669-39.264-22.669 39.264h-36.227l58.896-102.01 58.896 102.01z" fill="#34495e"/></g></g></svg>

+ 203 - 0
src/auto-imports.d.ts

@@ -0,0 +1,203 @@
+// Generated by 'unplugin-auto-import'
+export {}
+declare global {
+  const asyncComputed: typeof import('@vueuse/core')['asyncComputed']
+  const autoResetRef: typeof import('@vueuse/core')['autoResetRef']
+  const computedAsync: typeof import('@vueuse/core')['computedAsync']
+  const computedEager: typeof import('@vueuse/core')['computedEager']
+  const computedInject: typeof import('@vueuse/core')['computedInject']
+  const computedWithControl: typeof import('@vueuse/core')['computedWithControl']
+  const controlledComputed: typeof import('@vueuse/core')['controlledComputed']
+  const controlledRef: typeof import('@vueuse/core')['controlledRef']
+  const createEventHook: typeof import('@vueuse/core')['createEventHook']
+  const createGlobalState: typeof import('@vueuse/core')['createGlobalState']
+  const createInjectionState: typeof import('@vueuse/core')['createInjectionState']
+  const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn']
+  const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable']
+  const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn']
+  const debouncedRef: typeof import('@vueuse/core')['debouncedRef']
+  const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch']
+  const eagerComputed: typeof import('@vueuse/core')['eagerComputed']
+  const extendRef: typeof import('@vueuse/core')['extendRef']
+  const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch']
+  const isDefined: typeof import('@vueuse/core')['isDefined']
+  const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable']
+  const onClickOutside: typeof import('@vueuse/core')['onClickOutside']
+  const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke']
+  const onLongPress: typeof import('@vueuse/core')['onLongPress']
+  const onStartTyping: typeof import('@vueuse/core')['onStartTyping']
+  const pausableWatch: typeof import('@vueuse/core')['pausableWatch']
+  const reactify: typeof import('@vueuse/core')['reactify']
+  const reactifyObject: typeof import('@vueuse/core')['reactifyObject']
+  const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed']
+  const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit']
+  const reactivePick: typeof import('@vueuse/core')['reactivePick']
+  const refAutoReset: typeof import('@vueuse/core')['refAutoReset']
+  const refDebounced: typeof import('@vueuse/core')['refDebounced']
+  const refDefault: typeof import('@vueuse/core')['refDefault']
+  const refThrottled: typeof import('@vueuse/core')['refThrottled']
+  const refWithControl: typeof import('@vueuse/core')['refWithControl']
+  const resolveRef: typeof import('@vueuse/core')['resolveRef']
+  const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
+  const syncRef: typeof import('@vueuse/core')['syncRef']
+  const syncRefs: typeof import('@vueuse/core')['syncRefs']
+  const templateRef: typeof import('@vueuse/core')['templateRef']
+  const throttledRef: typeof import('@vueuse/core')['throttledRef']
+  const throttledWatch: typeof import('@vueuse/core')['throttledWatch']
+  const toReactive: typeof import('@vueuse/core')['toReactive']
+  const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount']
+  const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount']
+  const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted']
+  const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose']
+  const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted']
+  const unrefElement: typeof import('@vueuse/core')['unrefElement']
+  const until: typeof import('@vueuse/core')['until']
+  const useActiveElement: typeof import('@vueuse/core')['useActiveElement']
+  const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery']
+  const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter']
+  const useArrayFind: typeof import('@vueuse/core')['useArrayFind']
+  const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex']
+  const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin']
+  const useArrayMap: typeof import('@vueuse/core')['useArrayMap']
+  const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce']
+  const useArraySome: typeof import('@vueuse/core')['useArraySome']
+  const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue']
+  const useAsyncState: typeof import('@vueuse/core')['useAsyncState']
+  const useBase64: typeof import('@vueuse/core')['useBase64']
+  const useBattery: typeof import('@vueuse/core')['useBattery']
+  const useBluetooth: typeof import('@vueuse/core')['useBluetooth']
+  const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints']
+  const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel']
+  const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation']
+  const useCached: typeof import('@vueuse/core')['useCached']
+  const useClipboard: typeof import('@vueuse/core')['useClipboard']
+  const useColorMode: typeof import('@vueuse/core')['useColorMode']
+  const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog']
+  const useCounter: typeof import('@vueuse/core')['useCounter']
+  const useCssVar: typeof import('@vueuse/core')['useCssVar']
+  const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement']
+  const useCycleList: typeof import('@vueuse/core')['useCycleList']
+  const useDark: typeof import('@vueuse/core')['useDark']
+  const useDateFormat: typeof import('@vueuse/core')['useDateFormat']
+  const useDebounce: typeof import('@vueuse/core')['useDebounce']
+  const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn']
+  const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory']
+  const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion']
+  const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
+  const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
+  const useDevicesList: typeof import('@vueuse/core')['useDevicesList']
+  const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
+  const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
+  const useDraggable: typeof import('@vueuse/core')['useDraggable']
+  const useDropZone: typeof import('@vueuse/core')['useDropZone']
+  const useElementBounding: typeof import('@vueuse/core')['useElementBounding']
+  const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint']
+  const useElementHover: typeof import('@vueuse/core')['useElementHover']
+  const useElementSize: typeof import('@vueuse/core')['useElementSize']
+  const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility']
+  const useEventBus: typeof import('@vueuse/core')['useEventBus']
+  const useEventListener: typeof import('@vueuse/core')['useEventListener']
+  const useEventSource: typeof import('@vueuse/core')['useEventSource']
+  const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper']
+  const useFavicon: typeof import('@vueuse/core')['useFavicon']
+  const useFetch: typeof import('@vueuse/core')['useFetch']
+  const useFileDialog: typeof import('@vueuse/core')['useFileDialog']
+  const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess']
+  const useFocus: typeof import('@vueuse/core')['useFocus']
+  const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin']
+  const useFps: typeof import('@vueuse/core')['useFps']
+  const useFullscreen: typeof import('@vueuse/core')['useFullscreen']
+  const useGamepad: typeof import('@vueuse/core')['useGamepad']
+  const useGeolocation: typeof import('@vueuse/core')['useGeolocation']
+  const useIdle: typeof import('@vueuse/core')['useIdle']
+  const useImage: typeof import('@vueuse/core')['useImage']
+  const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll']
+  const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver']
+  const useInterval: typeof import('@vueuse/core')['useInterval']
+  const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn']
+  const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
+  const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
+  const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
+  const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
+  const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
+  const useMediaControls: typeof import('@vueuse/core')['useMediaControls']
+  const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
+  const useMemoize: typeof import('@vueuse/core')['useMemoize']
+  const useMemory: typeof import('@vueuse/core')['useMemory']
+  const useMounted: typeof import('@vueuse/core')['useMounted']
+  const useMouse: typeof import('@vueuse/core')['useMouse']
+  const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
+  const useMousePressed: typeof import('@vueuse/core')['useMousePressed']
+  const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver']
+  const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
+  const useNetwork: typeof import('@vueuse/core')['useNetwork']
+  const useNow: typeof import('@vueuse/core')['useNow']
+  const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl']
+  const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
+  const useOnline: typeof import('@vueuse/core')['useOnline']
+  const usePageLeave: typeof import('@vueuse/core')['usePageLeave']
+  const useParallax: typeof import('@vueuse/core')['useParallax']
+  const usePermission: typeof import('@vueuse/core')['usePermission']
+  const usePointer: typeof import('@vueuse/core')['usePointer']
+  const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
+  const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
+  const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
+  const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
+  const useRafFn: typeof import('@vueuse/core')['useRafFn']
+  const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
+  const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
+  const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation']
+  const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea']
+  const useScriptTag: typeof import('@vueuse/core')['useScriptTag']
+  const useScroll: typeof import('@vueuse/core')['useScroll']
+  const useScrollLock: typeof import('@vueuse/core')['useScrollLock']
+  const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage']
+  const useShare: typeof import('@vueuse/core')['useShare']
+  const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition']
+  const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis']
+  const useStepper: typeof import('@vueuse/core')['useStepper']
+  const useStorage: typeof import('@vueuse/core')['useStorage']
+  const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync']
+  const useStyleTag: typeof import('@vueuse/core')['useStyleTag']
+  const useSupported: typeof import('@vueuse/core')['useSupported']
+  const useSwipe: typeof import('@vueuse/core')['useSwipe']
+  const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList']
+  const useTextDirection: typeof import('@vueuse/core')['useTextDirection']
+  const useTextSelection: typeof import('@vueuse/core')['useTextSelection']
+  const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize']
+  const useThrottle: typeof import('@vueuse/core')['useThrottle']
+  const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn']
+  const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory']
+  const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo']
+  const useTimeout: typeof import('@vueuse/core')['useTimeout']
+  const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn']
+  const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll']
+  const useTimestamp: typeof import('@vueuse/core')['useTimestamp']
+  const useTitle: typeof import('@vueuse/core')['useTitle']
+  const useToggle: typeof import('@vueuse/core')['useToggle']
+  const useTransition: typeof import('@vueuse/core')['useTransition']
+  const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams']
+  const useUserMedia: typeof import('@vueuse/core')['useUserMedia']
+  const useVModel: typeof import('@vueuse/core')['useVModel']
+  const useVModels: typeof import('@vueuse/core')['useVModels']
+  const useVibrate: typeof import('@vueuse/core')['useVibrate']
+  const useVirtualList: typeof import('@vueuse/core')['useVirtualList']
+  const useWakeLock: typeof import('@vueuse/core')['useWakeLock']
+  const useWebNotification: typeof import('@vueuse/core')['useWebNotification']
+  const useWebSocket: typeof import('@vueuse/core')['useWebSocket']
+  const useWebWorker: typeof import('@vueuse/core')['useWebWorker']
+  const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn']
+  const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus']
+  const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll']
+  const useWindowSize: typeof import('@vueuse/core')['useWindowSize']
+  const watchArray: typeof import('@vueuse/core')['watchArray']
+  const watchAtMost: typeof import('@vueuse/core')['watchAtMost']
+  const watchDebounced: typeof import('@vueuse/core')['watchDebounced']
+  const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable']
+  const watchOnce: typeof import('@vueuse/core')['watchOnce']
+  const watchPausable: typeof import('@vueuse/core')['watchPausable']
+  const watchThrottled: typeof import('@vueuse/core')['watchThrottled']
+  const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable']
+  const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
+  const whenever: typeof import('@vueuse/core')['whenever']
+}

+ 38 - 0
src/components.d.ts

@@ -0,0 +1,38 @@
+// generated by unplugin-vue-components
+// We suggest you to commit this file into source control
+// Read more: https://github.com/vuejs/core/pull/3399
+import '@vue/runtime-core'
+
+export {}
+
+declare module '@vue/runtime-core' {
+  export interface GlobalComponents {
+    ButtonPrimary: typeof import('./components/shared/ButtonPrimary.vue')['default']
+    ButtonSecondary: typeof import('./components/shared/ButtonSecondary.vue')['default']
+    Feature: typeof import('./components/Feature.vue')['default']
+    Features: typeof import('./components/Features.vue')['default']
+    Heading1: typeof import('./components/shared/Heading1.vue')['default']
+    Heading2: typeof import('./components/shared/Heading2.vue')['default']
+    Hero: typeof import('./components/Hero.vue')['default']
+    Home: typeof import('./pages/home/home.vue')['default']
+    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']
+    MdiAlien: typeof import('~icons/mdi/alien')['default']
+    MdiArrowRight: typeof import('~icons/mdi/arrow-right')['default']
+    MdiGithub: typeof import('~icons/mdi/github')['default']
+    MdiMoonWaningCrescent: typeof import('~icons/mdi/moon-waning-crescent')['default']
+    MdiWhiteBalanceSunny: typeof import('~icons/mdi/white-balance-sunny')['default']
+    Navbar: typeof import('./components/Navbar.vue')['default']
+    RouterLink: typeof import('vue-router')['RouterLink']
+    RouterView: typeof import('vue-router')['RouterView']
+    UiDevider: typeof import('./components/ui-devider/ui-devider.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']
+    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']
+    UiVipArticle: typeof import('./components/ui-vip-article/ui-vip-article.vue')['default']
+  }
+}

+ 31 - 0
src/components/Feature.vue

@@ -0,0 +1,31 @@
+<script setup lang="ts">
+defineProps({
+  title: { type: String, required: true },
+  text: { type: String, required: true },
+  url: { type: String, required: true },
+})
+</script>
+
+<template>
+  <div
+    class="flex flex-col h-full p-8 bg-gray-100 rounded-lg items dark:bg-gray-700"
+  >
+    <Heading2>
+      {{ title }}
+    </Heading2>
+
+    <div class="flex flex-col flex-grow">
+      <p class="flex-grow text-base leading-relaxed dark:text-gray-300">
+        {{ text }}
+      </p>
+      <a
+        :href="url"
+        target="_blank"
+        class="inline-flex items-center mt-3 text-green-500"
+      >
+        Learn More
+        <MdiArrowRight class="ml-1" />
+      </a>
+    </div>
+  </div>
+</template>

+ 54 - 0
src/components/Features.vue

@@ -0,0 +1,54 @@
+<template>
+  <section class="container px-5 py-12 mx-auto text-gray-600 body-font">
+    <div class="flex flex-col w-full mb-8 text-center">
+      <Heading1> Installed Vite plugins 📦 </Heading1>
+      <p class="dark:text-gray-300">
+        You can even find more awesome Vite plugins
+        <a
+          href="https://github.com/vitejs/awesome-vite"
+          target="_blank"
+          class="text-green-500"
+        >
+          here
+        </a>
+      </p>
+    </div>
+    <div class="flex flex-wrap -m-2">
+      <div class="w-full p-2 md:w-1/2 lg:w-1/3">
+        <Feature
+          title="⚡️ @vitejs/plugin-vue2"
+          text="Vue 2 support for Vite"
+          url="https://github.com/vitejs/vite-plugin-vue2"
+        />
+      </div>
+      <div class="w-full p-2 md:w-1/2 lg:w-1/3">
+        <Feature
+          title="📦 unplugin-components"
+          text="Importing Vue components on-demand"
+          url="https://github.com/antfu/unplugin-vue-components"
+        />
+      </div>
+      <div class="w-full p-2 md:w-1/2 lg:w-1/3">
+        <Feature
+          title="📥 unplugin-auto-import"
+          text="Importing APIs like CompositionAPI on-demand"
+          url="https://github.com/antfu/unplugin-auto-import"
+        />
+      </div>
+      <div class="w-full p-2 md:w-1/2 lg:w-1/3">
+        <Feature
+          title="🎨 vite-plugin-windicss"
+          text="Easy WindiCSS integration"
+          url="https://github.com/windicss/vite-plugin-windicss"
+        />
+      </div>
+      <div class="w-full p-2 md:w-1/2 lg:w-1/3">
+        <Feature
+          title="😃 unplugin-icons"
+          text="Importing icons as Vue components on-demand"
+          url="https://github.com/antfu/unplugin-icons"
+        />
+      </div>
+    </div>
+  </section>
+</template>

+ 25 - 0
src/components/Hero.vue

@@ -0,0 +1,25 @@
+<template>
+  <section
+    class="container flex flex-col items-center px-5 py-12 mx-auto text-gray-600 body-font md:flex-row"
+  >
+    <div class="w-5/6 mb-10 lg:max-w-lg lg:w-full md:w-1/2 md:mb-0">
+      <img
+        class="object-cover object-center rounded"
+        alt="Vue logo"
+        src="@/assets/vue-logo.svg"
+      >
+    </div>
+    <div
+      class="flex flex-col items-center text-center lg:flex-grow md:w-1/2 lg:pl-24 md:pl-16 md:items-start md:text-left"
+    >
+      <Heading1> Vite ⚡ - Vue 2 starter template </Heading1>
+      <p class="mb-8 leading-relaxed dark:text-gray-300">
+        This example project shows how to speed up your Vue 2 application with
+        the next generation frontend tooling Vite.
+      </p>
+      <a href="https://vuejs.org/v2/guide/" target="_blank">
+        <ButtonPrimary> Vue docs </ButtonPrimary>
+      </a>
+    </div>
+  </section>
+</template>

+ 69 - 0
src/components/Navbar.vue

@@ -0,0 +1,69 @@
+<script setup lang="ts">
+import { computed, getCurrentInstance } from 'vue'
+import { routes } from '@/router'
+
+// Import config from .env
+const appName = import.meta.env.VITE_APP_NAME
+
+const availableRoutes = routes.filter(route => route.name !== 'NotFound')
+const currentRoute = computed(() => getCurrentInstance()?.proxy?.$route)
+
+const isDark = useDark()
+const toggle = useToggle(isDark)
+</script>
+
+<template>
+  <header class="text-gray-600 body-font dark:bg-gray-800">
+    <div
+      class="container flex flex-col flex-wrap items-center p-5 mx-auto md:flex-row"
+    >
+      <RouterLink
+        :to="{ name: 'Home' }"
+        class="flex items-center mb-4 font-medium text-gray-900 title-font md:mb-0"
+      >
+        <img alt="Vite logo" src="@/assets/vite-logo.svg" width="36px">
+        <span class="ml-3 text-xl dark:text-white">
+          {{ appName }}
+        </span>
+      </RouterLink>
+      <nav
+        class="flex flex-wrap items-center justify-center text-base md:ml-auto"
+      >
+        <RouterLink
+          v-for="(route, index) in availableRoutes"
+          :key="index"
+          class="mr-5 font-semibold cursor-pointer"
+          :class="{
+            'text-green-500 hover:green-500 dark:text-green-500 dark:hover:text-green-500 underline':
+              route.name === currentRoute.name,
+            'hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-200':
+              route.name !== currentRoute.name,
+          }"
+          :to="{ name: route.name }"
+        >
+          {{ route.name }}
+        </RouterLink>
+        <RouterLink
+          class="flex items-center justify-center mr-2 text-black w-9 h-9 dark:text-white"
+          to="/aliens"
+        >
+          <MdiAlien />
+        </RouterLink>
+        <a
+          href="https://github.com/lstoeferle/vite-vue2-windicss-starter"
+          target="_blank"
+          class="flex items-center justify-center mr-2 text-black w-9 h-9 dark:text-white"
+        >
+          <MdiGithub />
+        </a>
+        <button
+          class="flex items-center justify-center w-9 h-9 focus:outline-none"
+          @click="toggle()"
+        >
+          <MdiWhiteBalanceSunny v-if="isDark" class="text-yellow-500" />
+          <MdiMoonWaningCrescent v-else class="text-gray-800" />
+        </button>
+      </nav>
+    </div>
+  </header>
+</template>

+ 14 - 0
src/components/layout-basic/layout-basic.vue

@@ -0,0 +1,14 @@
+<template>
+  <div class="w-screen flex h-screen flex-col items-center">
+    <ui-nav-bar></ui-nav-bar>
+    <div class="flex-1 overflow-y-auto">
+      <RouterView />
+    </div>
+  </div>
+</template>
+
+<script>
+export default {};
+</script>
+
+<style lang="scss" scoped></style>

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

@@ -0,0 +1,7 @@
+<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>

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

@@ -0,0 +1,7 @@
+<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>

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

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

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

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

+ 15 - 0
src/components/ui-devider/ui-devider.vue

@@ -0,0 +1,15 @@
+<template>
+    <div class="w-full h-2px bg-[#f7f7f7]">
+
+    </div>
+</template>
+
+<script>
+    export default {
+        
+    }
+</script>
+
+<style >
+
+</style>

+ 37 - 0
src/components/ui-main-article/ui-main-article.vue

@@ -0,0 +1,37 @@
+<template>
+    <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>
+        <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>
+</template>
+
+<script>
+    export default {
+        
+    }
+</script>
+
+<style >
+
+</style>

+ 65 - 0
src/components/ui-nav-bar/ui-nav-bar.vue

@@ -0,0 +1,65 @@
+<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="menu-item selected">
+        {{ $t("首页") }}
+      </div>
+      <div class="w-40px"></div>
+      <div class="menu-item">{{ $t("推荐") }}</div>
+      <div class="w-40px"></div>
+      <div class="menu-item">{{ $t("分类浏览") }}</div>
+      <div class="w-40px"></div>
+      <div class="menu-item">{{ $t("实时新闻") }}</div>
+      <div class="w-40px"></div>
+      <div class="menu-item">{{ $t("vip专区") }}</div>
+      <div class="w-40px"></div>
+      <div class="menu-item">{{ $t("关于我们") }}</div>
+      <div class="w-260px"></div>
+      <div class="menu-item">
+        <img class="w-30px object-contain" src="/tougao.png" />
+        {{ $t("投稿") }}
+      </div>
+      <div class="w-36px"></div>
+      <div class="menu-item">
+        <img class="w-30px object-contain" src="/search.png" />
+        {{ $t("搜索") }}
+      </div>
+      <div class="w-40px"></div>
+      <div class="menu-item">
+        {{ $t("登录注册") }}
+      </div>
+      <div class="w-44px"></div>
+      <div
+        class="w-30px h-30px rounded-full border-white-2px text-white align-middle text-center cursor-pointer"
+      >
+        {{ $t("cn") }}
+      </div>
+    </div>
+    <!-- <div class="min-h-272px w-screen bg-white absolute top-80px"></div> -->
+  </div>
+</template>
+
+<script>
+export default {
+  mounted() {
+    // this.$i18n.locale = "zh-TW";
+  },
+};
+</script>
+
+<style>
+.menu-item {
+  @apply text-white text-size-20px cursor-pointer relative h-full flex items-center;
+}
+.menu-item.selected::after {
+  content: "";
+  width: 100%;
+  height: 3px;
+  background: #fff;
+  position: absolute;
+  bottom: 14px;
+  left: 0;
+  border-radius: 3px;
+}
+</style>

+ 24 - 0
src/components/ui-portal/ui-portal.vue

@@ -0,0 +1,24 @@
+<script>
+	export default {
+		name: 'ui-teleport',
+		props: {
+			/* 移动至哪个标签内,最好使用id */
+			to: {
+				type: String,
+				required: true
+			}
+		},
+
+		mounted() {
+			document.querySelector(this.to).appendChild(this.$el)
+		},
+
+		destroyed() {
+			document.querySelector(this.to).removeChild(this.$el)
+		},
+
+		render() {
+			return this.$scopedSlots.default()
+		}
+	}
+</script>

+ 12 - 0
src/components/ui-shadow-box/ui-shadow-box.vue

@@ -0,0 +1,12 @@
+<template>
+  <div  class="rounded-3px shadow-[0px 3px 6px 0px rgba(0, 0, 0, 0.1)] bg-white">
+      
+    <slot></slot>
+  </div>
+</template>
+
+<script>
+export default {};
+</script>
+
+<style></style>

+ 29 - 0
src/components/ui-small-article/ui-small-article.vue

@@ -0,0 +1,29 @@
+<template>
+  <div class="flex bg-white items-center h-87px">
+    <div class="relative">
+      <img class="w-116px h-65px 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>
+    <div class="w-10px"></div>
+    <div class="flex flex-col flex-1 h-full">
+      <div class="h-12px"></div>
+      <div class="flex-col flex justify-between h-full items-end">
+        <div class="w-full text-size-14px text-[#000] font-normal">
+          这里是轮播图推荐内容标题这里是轮播图推荐内容标题
+        </div>
+
+        <div class="text-[#B8B8B8] text-size-14px font-medium">2803浏览</div>
+      </div>
+      <div class="h-14px"></div>
+    </div>
+  </div>
+</template>
+
+<script>
+export default {};
+</script>
+
+<style></style>

+ 81 - 0
src/components/ui-swiper/ui-swiper.vue

@@ -0,0 +1,81 @@
+<template>
+  <div v-bind="$attrs" class="relative">
+    <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" />
+      </swiper-slide>
+    </swiper>
+    <div class="absolute bottom-22px right-12px z-50 flex">
+      <div
+        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>
+
+<script>
+import { nanoid } from "nanoid";
+import { Swiper, SwiperSlide } from "vue-awesome-swiper";
+import "swiper/swiper-bundle.min.css";
+
+import SwiperCore, { Pagination } from "swiper/core";
+
+// install Swiper modules
+SwiperCore.use([Pagination]);
+export default {
+  components: {
+    Swiper,
+    SwiperSlide,
+  },
+  props: {
+    items: {
+      default: [],
+    },
+  },
+  computed: {
+    paginationId: () => nanoid(6),
+    swiperOption: () => ({
+      slidesPerView: 1,
+
+      // loop: true,
+    }),
+  },
+
+  data() {
+    return {
+      activeIndex: 0,
+    };
+  },
+
+  methods: {
+    change(index) {
+      console.log(index);
+    },
+  },
+  mounted() {
+    this.$refs.swiper.$swiper.on("activeIndexChange", (swiper) => {
+      this.activeIndex = swiper.activeIndex;
+    });
+  },
+};
+</script>
+<style>
+.swiper-pagination-bullet-active {
+  @apply bg-white;
+}
+.swiper-pagination-bullet {
+  @apply bg-rgba(255,255,255,1);
+}
+.dot {
+  @apply w-12px h-12px rounded-full bg-[rgba(255,255,255,0.3)] mr-10px;
+}
+.dot.selected {
+  @apply bg-white;
+}
+</style>

+ 22 - 0
src/components/ui-vip-article/ui-vip-article.vue

@@ -0,0 +1,22 @@
+<template>
+  <div class="h-157px flex items-center ">
+    <!-- <div class="mr-12.5px">
+      
+    </div> -->
+    <img src="/imgs/vip-cover1.png" class="w-100px h-133px object-cover mr-12.5px" />
+    <div class="flex flex-col h-full">
+      <div class="h-20.5px"></div>
+
+      <div class="flex flex-1 flex-col justify-between">
+        <div class="h-28px text-size-14px font-normal text-black ">
+          这里是期刊名这里是期刊名 是期
+        </div>
+        <div class="text-size-14px font-normal text-[#686868]">每389期</div>
+        <div class="text-size-14px font-normal text-[#686868]">January 2017</div>
+        <div class="text-size-14px font-normal text-[#686868]">共20篇</div>
+      </div>
+
+      <div class="h-18px"></div>
+    </div>
+  </div>
+</template>

+ 12 - 0
src/locales/zh-CN.js

@@ -0,0 +1,12 @@
+export default {
+  首页: "首页",
+  推荐: "推荐",
+  分类浏览: "分类浏览",
+  实时新闻: "实时新闻",
+  VIP专区: "VIP专区",
+  关于我们: "关于我们",
+  投稿: "投稿",
+  搜索: "搜索",
+
+  登录注册: "登录/注册",
+};

+ 3 - 0
src/locales/zh-TW.js

@@ -0,0 +1,3 @@
+export default {
+    "搜索": "搜索繁体"
+}

+ 30 - 0
src/main.js

@@ -0,0 +1,30 @@
+import Vue from "vue";
+import App from "@/App.vue";
+import VueI18n from "vue-i18n";
+
+import 'virtual:windi.css'
+import router from "@/router";
+import zhCN from "./locales/zh-CN";
+import zhTW from "./locales/zh-TW";
+
+
+Vue.config.productionTip = false;
+Vue.config.devtools = true;
+
+Vue.use(VueI18n);
+const messages = {
+  "zh-CN": zhCN,
+  "zh-TW": zhTW,
+};
+const i18n = new VueI18n({
+  locale: "zh-CN", // set locale
+  messages, // set locale messages
+});
+
+/* eslint-disable no-new */
+new Vue({
+  el: "#app",
+  router,
+  render: (h) => h(App),
+  i18n,
+});

+ 7 - 0
src/pages/home/_components/home-new.vue

@@ -0,0 +1,7 @@
+<template>
+  <ui-shadow-box class="relative h-50px flex items-center pl-16.5px">
+    <div class="w-158px h-3px absolute left-0 top--3px bg-primary rounded-full"></div>
+    <img class="w-36px mr-6.5px" src="/imgs/new.png" />
+    <div class="font-thin text-[#000] text-size-20px">{{ $t("最新文章") }}</div>
+  </ui-shadow-box>
+</template>

+ 24 - 0
src/pages/home/_components/home-tags.vue

@@ -0,0 +1,24 @@
+<template>
+  <ui-shadow-box class="bg-white pl-20px pr-8px pt-20px pb-10px">
+    <div class="mb-8.5px font-thin text-size-20px">{{ $t("热门导航") }}</div>
+
+    <ui-devider></ui-devider>
+    <div class="h-12.5px"></div>
+    <div class="flex flex-wrap">
+      <div class="tag selected">热门标签</div>
+      <div v-for="(item, index) in 18" :key="index" class="tag">热门标签</div>
+    </div>
+  </ui-shadow-box>
+</template>
+
+<script>
+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;
+}
+.tag.selected {
+  @apply bg-primary text-white;
+}
+</style>

+ 77 - 0
src/pages/home/home.vue

@@ -0,0 +1,77 @@
+<template>
+  <div>
+    <div class="h-20px"></div>
+
+    <ui-swiper :items="banner1" class="w-600px h-337px"></ui-swiper>
+    <div class="h-20px"></div>
+    <div class="w-1200px flex justify-between">
+      <div class="left w-860px">
+        <home-tags></home-tags>
+        <div class="h-20px"></div>
+        <home-new></home-new>
+        <div class="h-20px"></div>
+        <div v-for="item in 8" :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>
+
+          <div v-for="item in 4" :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 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="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>
+
+          <div v-for="item in 4" :key="item">
+            <ui-vip-article></ui-vip-article>
+            <ui-devider></ui-devider>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+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" },
+      ],
+    };
+  },
+};
+</script>
+<style></style>

+ 33 - 0
src/router/index.ts

@@ -0,0 +1,33 @@
+import Vue from "vue";
+import type { RouteConfig } from "vue-router";
+import VueRouter from "vue-router";
+import Home from "@/pages/home/home.vue";
+import BasicLayout from "@/components/layout-basic/layout-basic.vue";
+
+Vue.use(VueRouter);
+
+export const routes: RouteConfig[] = [
+  {
+    path: "/",
+    name: "root",
+    // NOTE: you can also apply meta information
+    // meta: {authRequired: false }
+    component: BasicLayout,
+    children: [{ path: "/home", component: Home }],
+    // NOTE: you can also lazy-load the component
+    // component: () => import("@/views/About.vue")
+  },
+  {
+    path: "/:path(.*)",
+    name: "NotFound",
+    // component: NotFound,
+  },
+];
+
+const router = new VueRouter({
+  base: "/",
+  mode: "hash",
+  routes,
+});
+
+export default router;

+ 15 - 0
src/shims-tsx.d.ts

@@ -0,0 +1,15 @@
+import type Vue from 'vue'
+
+declare global {
+  namespace JSX {
+    // tslint:disable no-empty-interface
+    interface Element extends VNode {}
+    // tslint:disable no-empty-interface
+    interface ElementClass extends Vue {}
+    type IntrinsicElements = Record<string, any>
+  }
+
+  interface ImportMeta {
+    env: Record<any, string>
+  }
+}

+ 4 - 0
src/shims-vue.d.ts

@@ -0,0 +1,4 @@
+declare module '*.vue' {
+  import Vue from 'vue'
+  export default Vue
+}

+ 14 - 0
tailwind.config.js

@@ -0,0 +1,14 @@
+module.exports = {
+  darkMode: "class", // or 'media'
+  theme: {
+    extend: {
+      colors: {
+        'primary': '#124026',
+      }
+    }
+  },
+  variants: {
+    theme: {},
+  },
+  plugins: [],
+};

+ 43 - 0
tsconfig.json

@@ -0,0 +1,43 @@
+{
+  "compilerOptions": {
+    "target": "esnext",
+    "module": "esnext",
+    "strict": true,
+    "jsx": "preserve",
+    "importHelpers": true,
+    "allowJs": true,
+    "moduleResolution": "node",
+    "skipLibCheck": true,
+    "esModuleInterop": true,
+    "allowSyntheticDefaultImports": true,
+    "sourceMap": true,
+    "baseUrl": ".",
+    "types": [
+      "@vueuse/core"
+    ],
+    "paths": {
+      "@/*": ["src/*"]
+    },
+    "lib": [
+      "esnext",
+      "dom",
+      "dom.iterable",
+      "scripthost"
+    ]
+  },
+  "include": [
+    "src/**/*.ts",
+    "src/**/*.js",
+    "src/**/*.tsx",
+    "src/**/*.vue",
+    "src/**/*.d.ts",
+    "tests/**/*.ts",
+    "tests/**/*.tsx"
+, "src/main.js"  ],
+  "exclude": [
+    "node_modules"
+  ],
+  "vueCompilerOptions": {
+    "target": 2.7
+  }
+}

+ 47 - 0
vite.config.ts

@@ -0,0 +1,47 @@
+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'
+
+const config = defineConfig({
+  resolve: {
+    alias: {
+      '@': `${path.resolve(__dirname, 'src')}`,
+    },
+  },
+
+  build: {
+    minify: true,
+  },
+
+  plugins: [
+    vue(),
+    WindiCSS(),
+    Components({
+      dirs:['src/components','src/pages/**/_components'],
+      resolvers: [
+        IconsResolver({
+          componentPrefix: '',
+        }),
+      ],
+      dts: 'src/components.d.ts',
+    }),
+    Icons(),
+    AutoImport({
+      imports: [
+        '@vueuse/core',
+      ],
+      dts: 'src/auto-imports.d.ts',
+    }),
+  ],
+
+  server: {
+    port: 3333,
+  },
+})
+
+export default config

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 2898 - 0
yarn.lock