npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

gvt-ui-hero

v4.3.13

Published

GVT UI Components Library

Readme

gvt-ui-hero

无国际化 (请升级最新版本 4.3.3)

~~GVT UI Components Package @1.1.30 =>@1.0.4~~

国际化 (请升级最新版本 4.3.3)

~~GVT UI Components Package @2.0.2 (OEM 定制) @1.0.5 => @4.0.29~~

~~GVT UI Components Package @1.2.9 (登录语言选择) @1.0.3~~

~~GVT UI Components Package @1.2.8 (登录无语言选择) @1.0.2~~

~~GVT UI Components Package @4.2.4 (https改造)~~

版本升级-更新日志

  • [4.3.3] 新增公共路由iframe,通过UMS配置url访问不同地址
  • [4.3.1] 新增顶部菜单栏自定义下拉选项菜单
  • [4.2.9] 新增网页title标签,自定义标题,默认前缀为Astraea
  • [4.2.8] 新增生产环境(sugar),新增图片地址判断
  • [4.2.7] 新增菜单图标2个,新增头部消息提醒功能
  • [4.2.5] 新增菜单图标11个,解决菜单图标重复
  • [4.2.4] 处理error页 和 登录页 根据环境获取图片地址
  • [4.2.2] 根据当前环境,获取对应logo图片地址
  • [4.1.7] logo图片地址根据对应的环境展示,是否禁用时区
  • [4.1.6] 修复跳转澳洲优订购,导致测试环境跳转出错问题
  • [4.0.29] 解决子页面不会高亮的问题
  • [4.0.27] 解决侧边栏高亮的显示问题

如何使用

安装

npm install gvt-ui-hero --save

更新

npm update gvt-ui-hero

组件列表

  • hero-layout 布局组件

  • hero-icon 图标组件

  • hero-login 登录视图组件

  • hero-sidebar => hero-submenu 请勿单独使用

  • hero-header 请勿单独使用

  • hero-content 请勿单独使用

引用方式

  • 方法一
import Vue from "vue"
import HeroUI from "gvt-ui-hero"

Vue.use(HeroUI)
  • 方法二
<script src="./node_modules/gvt-ui-hero/dist/gvt-ui-hero.js"></script>

子系统对接公共组件

侧边栏进行跨系统跳转时, 会在 URL 中拼接 tokenlang 参数, 例如(假设当前语种为 en-US):

http://localhost:9090/#/user-manage/user-list?lang=en-US&token=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxIiwidWlkIjoiMSIsInVzZXJuYW1lIjoiYWRtaW4iLCJ0eXBlIjoiMCIsInN5c3RlbSI6MSwiZXhwIjoxNTUyMTEyNTQ4fQ.cbaPqFhI8mVLLKjdjZn-N9_faz_L7iMV_BuhrJU3mOaY6Luu4YH-U2M1bd_TjPGHY-xAr1U6APFXKxuTtwb5XybMrHdhHFQTDgMJtLbHxf2qvVcf-1XD7yYRM7gdHmyQtXNZGrGhsHlfHBL4YIzD-VNxnfM9nR2h6HaWbkMHBGQ

  • 因此各个子系统, 需要在 main.js 主入口函数中, 接收并缓存 语种参数:langJWT参数:token

  • gvt-header 组件在切换语言时, 会更新 localStorage 中的 GVT-I18N-LANGzh-CN, 但是 urllang 参数扔为旧值 en-US

  • 因此需要在 beforEach() 中我们需要手动移除 lang 参数, 为保证 url 的美观, 同时移除 token 参数

const cleanLangAndTokenQuery = (to, from , next) => {
  to.query.token && delete to.query.token
  if(to.query.lang) {
    delete to.query.lang
    if(from.path === to.path) {
      iView.LoadingBar.finish()
    }
    next({
      // 替换当前路由地址
      replace: true,
      path: to.path,
      params: to.params,
      query: to.query
    });
  } else {
    next();
  }
}

router.beforEach(to, from , next) => {
  if(to.query.lang) {
    // query.lang 存在时, 更新本地 lang
    Lang.setLang(to.query.lang)
  } else {
    // 若 query.lang 不存在, 且本地未缓存语种时, 默认将其置为 "zh-CN"
    !Lang.getLang() && Lang.setLang()
  }
  // 初始化 vue-i18n locale
  setI18nLanguage(Lang.getLang())

  // query.token 存在时, 更新本地 jwt
  if(to.query.token) {
    Auth.setToken(to.query.token)
  }

  // ... 其他代码
  // 在所有调用 next() 处, 将其替换为 cleanLangAndTokenQuery()
  // 例如:
    if(Auth.getToken()) {
    if(to.path === "/login" || to.path === "/") {
      next({path: "/console"});
      iView.LoadingBar.finish();
    } else {
      if(store.getters.user.id === ""){
        store.dispatch("FetchUserData").then(apps => {
          store.dispatch("InitPermissionByApps", apps).then(() => {
            cleanLangAndTokenQuery(to, from, next)
          })
        }).catch(error => {
          Auth.removeToken();
          next({ path: `/${error.redirect}` });
          iView.LoadingBar.finish();
        })
      }else{
        cleanLangAndTokenQuery(to, from, next)
      }
    }
  }else {
    if(accessRoutePath.indexOf(to.path) > -1) {
      cleanLangAndTokenQuery(to, from, next)
    }else {
      next({path: "/login"});
      iView.LoadingBar.finish();
    }
  }
}

Lang & Auth 工具模块

// Lang Module

const prefixLang = "GVT_I18N_LANG";

class Lang {

  constructor() {}

  static setLang(lang = "zh-CN") {
    return localStorage.setItem(prefixLang, lang);
  }

  static getLang() {
    return localStorage.getItem(prefixLang);
  }

  static removeLang() {
    return localStorage.removeItem(prefixLang);
  }

}

export default Lang;
// Auth Module

const prefixToken = "GVT_AUTH_TOKEN";

class Auth {

  constructor() {}

  static setToken(token) {
    return localStorage.setItem(prefixToken, token);
  }

  static getToken() {
    return localStorage.getItem(prefixToken);
  }

  static removeToken() {
    return localStorage.removeItem(prefixToken);
  }

  static logOut() {
    this.removeToken();
    window.location.hash = "/login";
  }

}

export default Auth;

面包屑导航

获取侧边栏数据

组件会自动获取当前侧边栏所匹配导航的 文本url, 并将其按层级关系添加至面包屑中, 例如:

  1. 若当前为单级菜单点击, 组件会获取其 文本 (如: 首页), 而后会获取其 url (如: http://example.com/), 而后显示在面包屑中, 此时面包屑显示: 首页

  2. 若当前为二级菜单点击, 组件会获取一级二级菜单, 参照第一步获取相应 文本url, 而后显示在面包屑中, 此时面包屑显示: 应用管理 > 产品管理

获取路由数据

// 产品管理 路由对象

const router = {
  path: "product-manage",
  name: "product-manage",
  component: () => import("@/components/container/ContainerBase"),
  redirect: { name: "product-list" },
  children: [
    {
      path: "/",
      name: "product-list",
      meta:{ title: "产品列表", redirect: true },
      component: () => import("@/views/admin/application-manage/product-manage/List")
    },
    {
      path: "create",
      name: "product-create",
      meta:{ title: "产品创建", redirect: true },
      component: () => import("@/views/admin/application-manage/product-manage/CreateOrUpdate")
    },
    {
      path: "edit/:id",
      name: "product-edit",
      meta:{ title: "产品编辑", redirect: true },
      component: () => import("@/views/admin/application-manage/product-manage/CreateOrUpdate")
    }
  ]
}

组件会根据 route-matched 自行解析出 meta: {redirect: true} 的路由, 并将其拼接在侧边栏数据后, 若当前 path 为: http://localhost:9090/#/application-manage/product-manage

此时 产品列表 包含 meta: {redirect: true}, 那么它将被添加至面包屑中, 此时面包屑显示: 应用管理 > 产品管理 > 产品列表

若将 产品列表 只为 meta: {redirect: false} 或不声明 redirect 键, 如: meta: {}, 那么它将不被添加至面包屑中, 此时面包屑显示: 应用管理 > 产品管理

hero-layout

Props

props | 说明 | 数据类型 | 备注 | 示例 ---- | ---- | ---- | ---- | --- env | 当前环境 | String | 根据环境判断显示的logo地址 | "dev" logo | 产品图片 | String | 侧边栏菜单顶部 LOGO 显示, 大部分情况无需传入 | "//47.75.105.17:22124/group1/M00/01/07/wKi5SlvrjQCAANGMAAAR2Ug-7l4909.png" locale | 语种 | String | required & ["zh-CN", "en-US"] | "zh-CN" username | 用户名称 | String | 通过 vuex getters 获取 | "Gvt Hero" appTarget | 产品编码 | String | 兼容 APOS 只显示自身产品数据, 非特殊情况无需传递 | "apos-tenant" disTranslation | 是否禁用语言切换 | Boolean | 默认显示语言切换框 | true disTimeZone | 是否禁用时区 | Boolean | 默认显示时区 | true disMsgTips | 是否显示消息图标 | Boolean | 默认不显示消息图标 | true msgCount | 徽标数 | Number, String | 数量为0,不显示徽标数 | 1 overflowCount | 徽标封顶的数字值 | Number, String | 默认封顶数99 | 999 pageTitle | 页面自定义标题 | String | 默认值Astraea | APOS is-show-tagsview | 是否显示标签页 | Boolean | 默认不显示标签页 | false menu-data | 侧边栏菜单数据 | Array | 通过 getUserRelatedData() 获取 route-matched | vue-router 匹配集合 | Array | 通过 this.$route.matched 获取 menu-info | 个人信息 | Boolean | 显示"个人信息"按钮, 默认 false menu-pwd | 修改密码 | Boolean | 显示"修改密码"按钮, 默认 false menu-signup | 注册 | Boolean | 显示"注册"按钮, 默认 false menu-signup | 注册 | Boolean | 显示"注册"按钮, 默认 false showSelect | 是否展示下拉选项 | Boolean | 默认 false selectTitle | 下拉选项标题 | String | 默认 后台切换 selectWidth | 下拉选项宽度 | Number, String | 默认 0,有默认最小值 selectData | 下拉选项数据 | Array | 默认 []

Events

events | 说明 ---- | ---- msg-count-click | 消息图标点击 user-info-click | 用户信息点击 user-pwd-click | 修改密码点击 user-signup-click | 注册点击 user-logout-click | 注销按钮点击 select-menu-click | 下拉选项按钮点击

# hero-layout 集成了 hero-header, hero-sidebar, hero-content
# 使用 hero-layout, 快速构建子系统的布局容器
# 你也可以参照 ./src/views/common/layouts.vue
# 以下示例是标准使用方法
# 若要禁用语言切换功能, 声明 dis-translation 即可
touch layouts.vue
<template>
  <hero-layout
    :env="env"
    :username="username"
    :menu-data="menuData"
    :route-matched="routeMatched"
    :locale="locale"
    menu-info
    menu-pwd
    menu-signup
    dis-translation
    :is-show-tagsview="false"
    :pageTitle="pageTitle"
    :showSelect="showSelect"
    :selectTitle="selectTitle"
    :selectWidth="selectWidth"
    :selectData="selectData"
    @select-menu-click="selectMenuClick"
    @user-info-click="userinfo"
    @user-pwd-click="userpwd"
    @user-signup-click="usersignup"
    @user-logout-click="userlogout">

    <div slot="content">
      <router-view></router-view>
    </div>

  </hero-layout>
</template>
import Lang from "@/utils/lang"

export default {
  data() {
    return {
      menuData: [],
      routeMatched: [],
      env: process.env.NODE_ENV,
      pageTitle: 'APOS',
      username: "Gvt Hero",
      locale: Lang.getLang(),
      // 自定义下拉选项参数
      showSelect: true,
      selectTitle: '自定义菜单选项',
      selectWidth: '180',
      selectData: [
        {
          roleCode: '0',
          roleName: "数字清关全链路后台",
        },
        {
          roleCode: '1',
          roleName: "数字清关物流公司后台",
        },
        {
          roleCode: '2',
          roleName: "数字清关清关公司后台",
        },
      ]
    };
  },

  watch: {
    $route() {
      this.routeMatched = this.$route.matched;
    }
  },

  created() {
    this.routeMatched = this.$route.matched;
  },

  mounted() {
    this.$nextTick(() => {
      this.fetchMenus();
    })
  },

  methods: {
    // 拉取菜单模拟数据
    fetchMenus() {
      fetch("/static/mock/sidebar.json")
        .then(response => {
          return response.json();
        })
        .then(menu => {
          setTimeout(() => {
            this.menuData = menu;
          }, 500);
        });
    },
    userinfo() {
      alert("userinfo");
    },
    userpwd() {
      alert("userpwd");
    },
    usersignup(){
       alert("usersignup");
    },
    userlogout() {
      alert("userlogout");
    },
   // 点击自定义选项
    selectMenuClick(param) {
      console.log(param)
    }
  }
};

hero-icon

集成了vue-svgicon, 请查看 vue-svgicon 相关文档

hero-login

# 子系统创建视图组件, 再使用 hero-login, 即可快速构建登录视图
touch Login.vue

props

prop | 说明 ---- | ---- locale | 语种, 可使用 .sync 修饰符进行双向绑定, 默认 "zh-CN" login-back-url | 后台登录背景图片地址 login-url | 后台登录图片地址 domain-icp-no | 域名备案号 callback | 通知组件已经获取到后端数据,更新合适的背景图片,默认 "false" pageTitle | 页面自定义标题 默认值Astraea

slot

默认插槽, 用以容纳第三方登录, 数据由 UMS supportType 获取

示例

<template>
  <hero-login
    @login="submit"
    :locale.sync="lang"
    :login-back-url="YOUR_IMAGE_URL"
    :login-url="YOUR_IMAGE_URL"
    :domain-icp-no="YOUR_ICP_NO"
    :callback="true"
    :pageTitle="pageTitle"
    >
  </hero-login>
</template>
$loginIconSrc() {
    if (!this.callback) {
        return this.loginUrl
    } else {
        return '//47.75.105.17:22124/group1/M00/01/07/wKi5SlvrjMOAQHHgAAKHbYU_e_w612.png'
    }
},
$loginSkinSrc() {
    if (!this.callback) {
        return this.loginBackUrl
    } else {
        return '//47.75.105.17:22124/group1/M00/01/07/wKi5SlvrjKSAc6R_AAIzKAUmJ-U070.png'
    }
},
$copyRight() {
    const currentYear = new Date().getFullYear()
    if (!this.callback) {
        return this.domainIcpNo
    }else{
        return `Copyright &copy; ${currentYear} Grand View Technology Pty Ltd`
    }
}
import Lang from "@/utils/lang";
import { setI18nLanguage } from "@/setup/i18n-setup";

export default {
  data() {
    return {
      pageTitle: 'APOS',
      lang: Lang.getLang()
    }
  },

  watch: {
    lang(lang) {
      setI18nLanguage(lang);
    }
  },

  methods: {
    submit(user) {
      // user: {username: "", password: ""}
      // 你需要自行 md5 password
      // 例如:
      // const params = Object.assign({}, user, {
      //   password: md5(user.password)
      // });
      // login(params)
      //   .then(response => {
      //     const jwt = response.data.token;
      //     Auth.setToken(jwt);
      //     this.$router.push("/");
      //   })
      //   .catch(error => {
      //     this.$Message.error("账户或密码错误");
      //   });
    }
  }
}

hero-error

props

prop | 说明 | 数据类型 | 示例 ---- | ---- | ---- | ---- code | 视图代码,默认 "404", 只提供"403","404","500" | String | "403" 、"404"、"500" pageTitle | 页面自定义标题 | String | 默认值Astraea | APOS

# 快速构建错误视图页
touch 404.vue
<template>
  <hero-error :locale="locale" :pageTitle="pageTitle"></hero-error>
</template>
import Lang from "@/utils/lang"

export default {
  name: "error-404",

  data() {
    return {
      pageTitle: 'APOS',
      locale: Lang.getLang()
    }
  }
};

iframe

解密接口密文

通过重写原生 XMLHttpRequest 的方式实现全局请求拦截器,对特定接口返回的密文进行解密,并修改 response/responseText 返回明文给上层(axios、ajax等)。

公共路由

/**
 * 公共路由组件
 */

// 内容区域 - 业务路由
const content = [
  {
    path: "/iframe",
    name: "iframe",
    meta: {
      redirect: true,
      // title: "iframe",
    },
    component: () => import("@/views/common/iframe"),
  },
]

// 全局区域 - 无头部和菜单
const component = [
  {
    path: "/403",
    name: "403",
    component: () =>import("@/views/common/403"),
  },
  {
    path: "/404",
    name: "404",
    component: () => import("@/views/common/404"),
  },
  {
    path: "/500",
    name: "500",
    component: () => import("@/views/common/500"),
  },
]

// 创建模块接口
export {
  content,
  component
}