Vitify Admin

website·Indexed 30 days ago

https://kingyue737.github.io/vitify-docs/

An opinionated admin starter template based on Vue 2.7 and Vite. It includes built-in support for Vuetify, TypeScript, Vue I18n v8.x, and vue-echarts, featuring a custom plugin system, route-level permissions via Navigation Guards, and API mocking with Mock Service Worker.

Tokens
6.9K
Snippets
40
Records
62
Agent score
75%

What's inside Vitify

  1. Overview of Vitify Admin starter template

    Vitify Admin is a concise, opinionated starter template based on Vue 2.7. It is designed to leverage the extensive Vue 2 ecosystem while backporting modern Vue 3 developer experience (DX) features. A key feature is the implementation of intellisense and type checking for Vuetify 2 by generating component types from web-types, overcoming the lack of official Volar support for Vuetify 2.
  2. Implement i18n in Vue 2 using Composition API

    To bring Vue I18n v9 features like the Composition API and message format syntax to Vue 2, use vue-i18n-bridge alongside Vue I18n v8.x. Note that in this setup, you should exclusively use the Composition API, as mixing Legacy and Composition APIs is not fully supported and not recommended.
  3. Understand navigation drawer generation logic

    The navigation drawer is automatically generated from routes and their metadata. It supports infinite nesting via a recursive component.

    Logic for nesting:

    • If a route has more than one child route, it becomes a nested menu item in the drawer.
    • If a route has exactly one child route, that child is displayed as a root route in the drawer.
  4. Create auto-imported plugins in Vitify

    Vitify uses a custom plugin system where all TypeScript (.ts) files located in the src/plugins folder are automatically imported. To create a plugin, export an install function that accepts a Vue instance. This approach is preferred over calling Vue.use() or Vue.component() directly to ensure plugins can be easily reused in unit and component testing.
    import type { InstallPlugin } from '@/utils/types'
    
    export const install: InstallPlugin = (vue) => {
      // do something
    }
  5. Use Vitify Nuxt for SPA or SSG development

    For developers seeking a better Vue experience and consistent maintenance, the Vitify Nuxt starter template is recommended. In addition to SSR, it works fully with Single Page Application (SPA) and Static Site Generation (SSG) modes.
  6. Manage global styles in Vitify Admin

    Global styles are located in the @/assets/styles directory. The project follows a workflow where global styles reside in this directory, while page-specific styles are defined within the respective .vue files using scoped SCSS.
    ├── styles
    │   ├── _overrides.scss          # global style overrides vuetify predefined style
    │   ├── _scrollbar.scss          # custom scrollbar style (only works in chromium)
    │   ├── _utils.scss              # style utils
    │   ├── index.scss               # entry point of global styles
    │   ├── variables.scss           # custom Sass variables
    │   └── vuetify-variables.scss   # custom Vuetify Sass variables
    <style scoped lang="scss">
    /* local styles */
    </style>
  7. Implement route-level permissions using Navigation Guards

    Vitify Admin manages route-level access by using Vue Router Navigation Guards. The system compares the user's roles (stored in userStore.roles) against the roles array defined in the route's meta information (route.meta.roles). If the route has no roles defined or if the user possesses one of the required roles (verified via isPermitted), access is granted; otherwise, the user is redirected to a 404 error page (named 'all').
    router.beforeEach(async (to, from, next) => {
      const userStore = useUserStore()
      // Determine whether the user has logged in
      if (userStore.token) {
        if (to.path === '/login') {
          // If is logged in, redirect to the home page
          next({ path: '/' })
        } else {
          // Check whether the user has obtained his permission roles
          if (userStore.roles.length === 0) {
            try {
              await userStore.getUserInfo()
            } catch (e) {
              // Remove token and redirect to login page
              userStore.resetToken()
              Message.error(e)
              next('/login')
              return
            }
          }
          // If user's role is permitted, go
          if (!to.meta?.roles || isPermitted(to.meta.roles)) {
            next()
            return
          }
          // Redirect to 404 error page if not permitted
          next({ name: 'all' })
        }
      } else {
        if (to.path === '/login') {
          next()
        } else {
          next('/login')
        }
      }
    })
  8. Implement API mocking with Mock Service Worker (MSW)

    Vitify Admin recommends using Mock Service Worker (MSW) for API mocking. MSW leverages Service Workers to intercept network requests at the network level, allowing developers to mock server responses without modifying application source code.
  9. Implement data visualization with vue-echarts in Vitify Admin

    Vitify Admin uses vue-echarts, a Vue.js wrapper for Apache ECharts. The component automatically handles resizing when the parent container changes and allows binding ECharts events using Vue's v-on directive. To optimize bundle size, it is recommended to manually import only the specific components and charts required from ECharts. These imports should be configured in src/plugins/echarts.ts.
  10. Manually define Vue 2 component methods for type checking

    To add type checking for component methods in SFC templates, extend the DefineComponent definition within the GlobalComponents interface. The DefineComponent type accepts several generics: Props, RawBindings, Data, Methods, and others.
    import type { DefineComponent, VNode } from '@vue/runtime-dom'
    
    declare module '@vue/runtime-dom' {
      export interface GlobalComponents {
        MyComponent: DefineComponent<
          Props,
          {
            $scopedSlots: {
              slotName: ({args: {propName: propType}}) => VNode[]
            }
          },
          {},
          {},
          Methods
        >
      }
    }
  11. Use Material Design Icons (MDI) with SVG replacement

    This template uses @mdi/js instead of @mdi/font to reduce bundle size. It utilizes @rollup/plugin-replace to automatically replace MDI icon names (e.g., mdi-bell) with their corresponding SVG paths during the build process. Developers can use the standard <v-icon> component as described in the Vuetify documentation. To revert to using @mdi/font, remove the replacement plugin from vite.config.ts.
    <!-- The following is replaced by an SVG path during build -->
    <v-icon>mdi-bell</v-icon>
  12. Handle snake_case and camelCase conversion between Python and TypeScript

    When using a Python backend (which follows PEP 8 snake_case) with a TypeScript frontend (which uses camelCase), use the axios-case-converter middleware. This Axios transformer/interceptor automatically converts keys between snake_case and camelCase, preventing the need to mix naming conventions within the source code.
    // @/utils/request.ts
    import applyCaseMiddleware from "axios-case-converter";
    import axios from "axios";
    
    const service = applyCaseMiddleware(
      axios.create({
        /* axios config */
      })
    );