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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pit-frontend-framework/utils

v1.0.2

Published

湖南创智艾泰克科技有限公司-前端组工具库

Readme

@pit-frontend-framework/utils

湖南创智艾泰克科技有限公司 — 前端工具库

为 Vue 3 + Vite 企业级项目提供开箱即用的工具函数、钩子与上下文注入能力。

pnpm add @pit-frontend-framework/utils

目录

| 模块 | 说明 | | :--- | :--- | | 应用配置 appConfig | 初始化与读取运行时配置 | | 运行时常量 define | 从 AppConfig 派生的响应式常量 | | 认证存储 auth | Token / Lock / PasswordLock 的 localStorage 读写 | | 请求客户端 request | 基于 axios 的可配置 HTTP 客户端 | | 权限上下文 permissionContext | 动态注入权限数据,提供 hasP / hasBtnP / hasFormP | | 路由上下文 routerContext | 注入当前路由解析函数 | | 日期工具 date | 多格式日期格式化、时间差计算 | | 对象工具 object | 深拷贝、深合并、URL 参数序列化等 | | 树形工具 tree | 树遍历、树扁平化、数组转树 | | 表单验证 form | 预置正则验证器、列过滤工具 | | 密码校验 password | 企业级密码复杂度校验 | | 存储适配器 storage | 带前缀的 localStorage 适配器 | | 浏览器工具 browser | DOM 操作、文件下载、文件大小格式化 | | 剪贴板 clipboard | 跨浏览器文本复制 | | 打印 print | 区域打印、内容生成 | | 事件总线 emitter | 基于 mitt 的全局事件总线 | | 跨标签广播 broadcastService | 基于 BroadcastChannel 的多标签通信 | | 国际化 i18n | 注入 vue-i18n 实例,内置中英文语言包 | | JWKS 加密 jwks | RSA 公钥加密(JWKS 协议) | | 本地缓存工具 localCache | URL 参数 / localStorage 快捷读取 | | 滚动工具 scroll | 缓动平滑滚动 | | 表格列宽 tableSize | 响应不同表格密度的列宽常量 | | 通用校验 validate | URL、邮件、经纬度等格式校验 | | 页面工具 page | 页面标题构建 | | 组件安装 install | Vue 组件 install 辅助函数 | | pit 业务集合 pit | 权限 / 流程 / 数字 / 日期等业务常用操作的聚合对象 | | 全局常量 constants | IS_OK、BIDTYPE 等通用业务常量 |


一、应用配置 appConfig

框架要求在 main.tscreateApp() 之前 调用初始化函数,其他模块的运行时常量依赖此配置。

AppConfig 接口

| 字段 | 类型 | 说明 | | :--- | :--- | :--- | | mode | string | 运行模式,如 'development' / 'production' | | baseUrl | string | 请求前缀(axios baseURL) | | timeout | number | 请求超时(ms) | | baseApi | string | 后台 API 地址前缀 | | loginTitle | string | 登录页面标题 | | loginAuthor | string | 登录页面著作 | | title | string | 网站标题 | | jm | string | 积木地址 | | sort | string | 排序服务地址 | | wssUrl | string | WebSocket URL | | bimApi | string | BIMWin URL | | enablePageOffice | boolean | 是否启用 PageOffice | | jwksKid | string? | JWKS 公钥 kid |

initAppConfigFromViteEnv(env, overrides?)

从 Vite 的 import.meta.env 初始化配置,自动完成 env var → AppConfig 字段的映射。

| 参数 | 类型 | 必填 | 说明 | | :--- | :--- | :--- | :--- | | env | Record<string, string \| boolean \| undefined> | 是 | import.meta.env | | overrides | Partial<AppConfig> | 否 | 覆盖任意字段 |

// main.ts
import { initAppConfigFromViteEnv } from '@pit-frontend-framework/utils';

initAppConfigFromViteEnv(import.meta.env);
// 或覆盖超时
initAppConfigFromViteEnv(import.meta.env, { timeout: 30000 });

约定的 env var 映射:

| env var | AppConfig 字段 | | :--- | :--- | | VITE_APP_DEFINE_BASE_URL | baseUrl | | VITE_APP_BASE_API | baseApi | | VITE_APP_DEFINE_LOGIN_TITLE | loginTitle | | VITE_APP_DEFINE_LOGIN_AUTHOR | loginAuthor | | VITE_APP_TITLE | title | | VITE_APP_JM | jm | | VITE_APP_SORT | sort | | VITE_APP_BASE_WSS | wssUrl | | VITE_APP_BIM_API | bimApi | | VITE_APP_ENABLE_PAGEOFFICE | enablePageOffice |

initAppConfig(config)

手动传入完整配置对象进行初始化(适用于非 Vite 环境)。

getAppConfig()

获取只读配置对象,未初始化时抛出错误。

import { getAppConfig } from '@pit-frontend-framework/utils';

const { baseUrl, title } = getAppConfig();

onAppConfigReady(cb)

注册回调,在配置初始化完成时执行;若已初始化则立即执行。适用于依赖配置的模块延迟初始化。


二、运行时常量 define

由 AppConfig 在初始化时自动填充的 ESM live binding 常量,无需手动赋值

import {
  DEFINE_MODE, DEFINE_BASE_URL, DEFINE_TITLE,
  DEFINE_LOGIN_TITLE, DEFINE_LOGIN_AUTHOR,
  WSS_URL, BIM_API, ENABLE_PAGEOFFICE,
  DEFINE_JWKS_KID, DEFINE_JWKS_PATH,
  DEFINE_JM, DEFINE_SORT, DEFINE_TIME,
} from '@pit-frontend-framework/utils';

原理:利用 ESM live bindings,initAppConfig() 调用后所有导入方自动获取最新值,无需重新导入。


三、认证存储 auth

对 localStorage 的 Token / Lock / PasswordLock 三类 key 进行统一管理,key 名称可自定义。

Token 操作

| 函数 | 签名 | 说明 | | :--- | :--- | :--- | | getToken | () => string \| null | 读取 token | | setToken | (token: string) => void | 写入 token | | removeToken | () => void | 删除 token |

Lock 操作

| 函数 | 签名 | 说明 | | :--- | :--- | :--- | | getLock<T> | () => T \| null | 读取锁屏数据(自动 JSON 反序列化) | | setLock | (value: unknown) => void | 写入锁屏数据 | | removeLock | () => void | 删除锁屏数据 |

PasswordLock 操作

与 Lock 操作对称,函数名为 getPasswordLock / setPasswordLock / removePasswordLock

自定义键名

import { setAuthStorageKeys, resetAuthStorageKeys } from '@pit-frontend-framework/utils';

setAuthStorageKeys({ token: 'my_token', lock: 'my_lock' });
// 恢复默认
resetAuthStorageKeys();

四、请求客户端 request

RequestHooks 接口

| 钩子 | 类型 | 说明 | | :--- | :--- | :--- | | onRequest | (config) => config | 请求前拦截(适合注入 token) | | onRequestError | (error) => unknown | 请求异常处理 | | onResponse | (response) => unknown | 响应成功处理(适合解包 data) | | onResponseError | (error) => unknown | 响应异常处理 |

createRequestClient(options?)

创建独立的 axios 实例,携带默认请求头与序列化配置。

| 参数 | 类型 | 必填 | 说明 | | :--- | :--- | :--- | :--- | | options.axiosConfig | CreateAxiosDefaults | 否 | 透传给 axios.create() | | options.hooks | RequestHooks | 否 | 局部生命周期钩子 |

  • 返回值AxiosInstance
// src/utils/request.ts
import { setRequestHooks } from '@pit-frontend-framework/utils';

setRequestHooks({
  onRequest: (config) => {
    const token = localStorage.getItem('token');
    if (token) config.headers.set('Authorization', `Bearer ${token}`);
    return config;
  },
  onResponse: (response) => response.data,
  onResponseError: (error) => {
    console.error(error);
    return Promise.reject(error);
  },
});

setRequestHooks(hooks?) / getRequestHooks() / resetRequestHooks()

配置全局默认拦截钩子。

优先级:局部 hooks > setRequestHooks 全局 hooks > window 回调(兼容兜底)

request(默认实例)

开箱即用的 axios 实例,baseURLtimeoutAppConfig 初始化后自动更新。

http

import { http } from '@pit-frontend-framework/utils';

const data = await http.request<UserInfo>({ url: '/api/user', method: 'GET' });

五、权限上下文 permissionContext

框架包不直接依赖宿主的 store,由宿主在启动时注入权限数据的解析函数。

setPermissionContext(ctx)

main.ts 中注入权限上下文:

import { setPermissionContext } from '@pit-frontend-framework/utils';
import { useUserStore } from '@/store';

setPermissionContext({
  getPermissionList: () => useUserStore().permissionList,
  getModelId: () => String(router.currentRoute.value.meta.modelId ?? ''),
});

PermissionContext 接口

| 字段 | 类型 | 说明 | | :--- | :--- | :--- | | getPermissionList | () => PermissionItem[] | 返回当前用户的权限列表 | | getModelId | () => string | 返回当前页面的 modelId | | getSnapshot | () => PermissionSnapshot | 返回权限快照(备用方式) | | storage | Storage | 自定义 storage(默认 localStorage) | | storageKeys | { administrator?, projectManager? } | 自定义存储键名 |

权限判断函数

| 函数 | 签名 | 说明 | | :--- | :--- | :--- | | hasP | (enCode: string) => boolean | 判断是否有指定列权限 | | hasBtnP | (enCode: string) => boolean | 判断是否有指定按钮权限 | | hasFormP | (enCode: string) => boolean | 判断是否有指定表单权限 | | adminAuthority | () => boolean | 是否为管理员 | | isProjectManager | () => boolean | 是否为项目经理 |

import { hasBtnP } from '@pit-frontend-framework/utils';

if (hasBtnP('btn_add')) {
  // 显示新增按钮
}

六、路由上下文 routerContext

框架包不直接依赖宿主路由,由宿主注入当前路由解析函数。

setRouteResolver(fn)

// main.ts
import { setRouteResolver } from '@pit-frontend-framework/utils';
import router from '@/router';

setRouteResolver(() => router.currentRoute.value);

getCurrentRoute()

返回 { params, query, meta } 的当前路由对象;未注入时返回空对象(安全降级)。

getRouter(type, queryType?)

从当前路由的 params / query / meta 中按 key 取值:

import { getRouter } from '@pit-frontend-framework/utils';

const projectId = getRouter('projectId');      // 自动从 params/query/meta 查找
const userId = getRouter('userId', 'query');   // 仅从 query 取

七、日期工具 date

toDate(v, format?)

将日期值格式化为字符串,支持秒级时间戳、毫秒级时间戳、/Date(timestamp)/ 格式、ISO 字符串。

| 参数 | 类型 | 默认值 | 说明 | | :--- | :--- | :--- | :--- | | v | Date \| string \| number \| null \| undefined | — | 日期值 | | format | string | 'yyyy-MM-dd HH:mm' | 格式模板(yyyy/MM/dd/HH/mm/ss) |

  • 返回值string,输入无效时返回 ''
import { toDate } from '@pit-frontend-framework/utils';

toDate(new Date(), 'yyyy-MM-dd');            // '2026-04-29'
toDate(1714348800, 'yyyy/MM/dd HH:mm:ss');   // 时间戳(秒)
toDate('2026-04-29T10:00:00');               // '2026-04-29 10:00'

dateFormat(date, fmt?)

基于 dayjs 的格式化,支持 YYYY/MM/DD/HH/mm/ss 等 dayjs token。

  • 返回值string

handleDateStr(dateStr)

yyyy-MM-dd 转换为 yyyy年MM月dd日 中文格式。

  • 返回值string

dateDiff(startDate, endDate)

计算两个日期字符串(yyyy-MM-dd)之间的天数差。

  • 返回值number

八、对象工具 object

deepClone<T>(source)

深拷贝,支持嵌套对象和数组。

import { deepClone } from '@pit-frontend-framework/utils';
const copy = deepClone({ a: { b: 1 } });

objectMerge<T>(target, source)

深合并两个对象,source 中已存在的键不会覆盖 target 中的同名键(保留 target 优先)。

cleanArray(arr)

过滤数组中的所有假值(含 0''nullundefined)。

param(obj)

对象序列化为 URL 查询字符串(忽略值为 undefined 的键)。

param({ a: 1, b: undefined, c: '中文' }); // 'a=1&c=%E4%B8%AD%E6%96%87'

param2Obj(url)

解析 URL 的查询字符串为对象。

appendObjectToPath(path, obj)

将对象参数追加到路径后:/api/list?a=1&b=2

formatFloat(val, decimals?, max?, min?, negative?)

数字格式化,限制小数位数和取值范围。

| 参数 | 类型 | 说明 | | :--- | :--- | :--- | | val | string \| number | 输入值 | | decimals | 2 \| 3 \| 4 | 小数位数,不传则只允许整数 | | max | number | 最大值 | | min | number | 最小值 | | negative | boolean | 是否允许负数 |

amountThousandsConversion(amount, decimals?)

金额千分位格式化,如 1234567.89'1,234,567.89'

uniqueArr<T>(arr)

数组去重。

createUniqueString()

生成唯一字符串(Date.now().toString(36) + 随机后缀)。

byteLength(str)

计算字符串字节长度(中文按 3 字节计算)。


九、树形工具 tree

TreeNode 接口

interface TreeNode {
  children?: TreeNode[] | null;
  hasChildren?: boolean;
  id?: string | number;
  parentId?: string | number;
  [key: string]: unknown;
}

iterationArr(nodes, cb, childrenKey?)

递归遍历节点数组及其所有子节点。

import { iterationArr } from '@pit-frontend-framework/utils';

iterationArr(treeData, (node) => {
  node.disabled = true;
});

iterationArrEnd(nodes, cb, childrenKey?)

同上,但回调返回 false 时提前终止遍历。

treeToArray<T>(list)

树形结构扁平化为数组(深拷贝,不修改原数据,子节点 children 置为 null)。

import { treeToArray } from '@pit-frontend-framework/utils';

const flat = treeToArray(treeData);

arrayToTree(items, config?)

扁平数组按 parentId 构建标准树结构(children 字段)。

toTreeViewJson(items)

扁平数组转为 TreeView JSON(ChildNodes 字段,根节点 parentId0'0')。


十、表单验证 form

formValidate(type, msg?)

创建 Element Plus el-form-item 规则使用的验证函数。

| 参数 | 类型 | 必填 | 说明 | | :--- | :--- | :--- | :--- | | type | FormValidateType \| string | 是 | 预置类型名称 或 自定义正则字符串如 '/^foo$/' | | msg | string | 否 | 自定义错误消息 |

  • 返回值(rule, value, callback) => void

预置类型(FormValidateType):

| key | 含义 | | :--- | :--- | | iphone | 手机号 | | password | 6-16 位数字+字母混合密码 | | idCard | 身份证号 | | email | 邮箱 | | plateNumber | 车牌号 | | chinese | 纯中文 | | enCode | 字母/数字开头结尾,中间可含小数点 | | userAccount | 纯数字英文 | | english | 纯英文 | | fullName | 不含特殊符号 | | bigInt | 正整数 | | netUrl | http/ftp/file URL |

import { formValidate } from '@pit-frontend-framework/utils';

const rules = {
  phone: [{ validator: formValidate('iphone') }],
  custom: [{ validator: formValidate('/^[A-Z]{3}$/', '必须是三位大写字母') }],
};

handleRules(simpleRules, extraRules?)

批量构建简写表单规则:字符串值自动转为 { required: true, message, trigger: ['input'] }

import { handleRules } from '@pit-frontend-framework/utils';

const rules = handleRules({ name: '请输入名称', code: '请输入编码' });

filterColumns(columns, hasFlow, insertIndex?, approvalColumn?)

根据流程状态决定是否插入审批状态列(prop: 'approvalStatus')。

toggleColumnByProp(columns, show, prop, column?, insertIndex?)

通用列切换:按 prop 动态插入或移除指定列。


十一、密码校验 password

passwordValidate(pwd)

验证密码是否满足企业级复杂度要求:

  • 12-16 位

  • 包含数字、大写字母、小写字母、特殊字符四类

  • 不能有连续 4 位相同字符

  • 不能有连续 4 位字母/数字/键盘横向/斜向序列

  • 返回值boolean

checkPasswordComplexity(pwd)

返回详细校验结果 { valid, message },消息支持 i18n。

import { checkPasswordComplexity } from '@pit-frontend-framework/utils';

const { valid, message } = checkPasswordComplexity('Abc123!@#xyz');
if (!valid) ElMessage.error(message);

十二、存储适配器 storage

createStorage(options?)

创建带前缀的存储适配器,值自动 JSON 序列化/反序列化。

| 参数 | 类型 | 说明 | | :--- | :--- | :--- | | options.prefix | string | key 前缀,默认 '' | | options.storage | Storage | 底层存储,默认 localStorage(SSR 自动降级为内存存储) |

  • 返回值StorageAdapter
import { createStorage } from '@pit-frontend-framework/utils';

const store = createStorage({ prefix: 'app_' });
store.set({ theme: 'dark', lang: 'zh' });
store.get<string>('theme');  // 'dark'
store.remove('theme');
store.clear();  // 仅清除 app_ 前缀的 key

全局快捷函数

import { storageGet, storageSet, storageRemove, storageClear } from '@pit-frontend-framework/utils';

storageSet({ userId: '123' });
storageGet('userId');  // '123'

十三、浏览器工具 browser

DOM 操作

| 函数 | 签名 | 说明 | | :--- | :--- | :--- | | hasClass | (el, cls) => boolean | 判断是否有 class | | addClass | (el, cls) => void | 添加 class | | removeClass | (el, cls) => void | 移除 class | | toggleClass | (el, cls) => void | 切换 class | | html2Text | (html) => string | 提取 HTML 纯文本 |

文件操作

| 函数 | 签名 | 说明 | | :--- | :--- | :--- | | fileType | (ext) => string | 后缀 → 文件类型分类(image/document/video/audio/archive/other) | | formatFileSize | (size) => string | 字节数 → '1.23 MB' | | downloadTemplate | (blob, fileName) => void | Blob 下载 | | downloadTemplateAddType | (res, fallbackName) => void | 从响应头提取文件名并下载 Blob | | downloadUrlFile | (url, fileName) => Promise<void> | 从 URL 下载文件 |

import { formatFileSize } from '@pit-frontend-framework/utils';

formatFileSize(1048576);  // '1.00 MB'

路由跳转

| 函数 | 说明 | | :--- | :--- | | goToRouteWithThePlatform(url, target, cb?, timer?) | 系统内部 hash 路由跳转(延迟 1s) | | goToRouteOutThePlatform(url, target, cb?, timer?) | 外部链接跳转 |


十四、剪贴板 clipboard

copyClipboard(text, options?)

复制文本到剪贴板。优先使用 navigator.clipboard,降级到 execCommand('copy')

| 参数 | 类型 | 说明 | | :--- | :--- | :--- | | text | string | 要复制的文本 | | options.onError | (error) => void | 复制失败回调 |

  • 返回值Promise<boolean>
import { copyClipboard, setClipboardFeedbackHandler } from '@pit-frontend-framework/utils';
import { ElMessage } from 'pit-element-plus';

// 全局配置复制反馈(一次性设置)
setClipboardFeedbackHandler(({ message, type }) => ElMessage({ message, type }));

await copyClipboard('Hello World');

十五、打印 print

Print(target, options?)

在隐藏 iframe 中执行区域打印,自动注入当前页面样式。

| 参数 | 类型 | 说明 | | :--- | :--- | :--- | | target | string \| HTMLElement \| { $el: HTMLElement } | 选择器、DOM 元素或 Vue 组件实例 | | options.noPrint | string | 不打印的元素选择器,默认 '.no-print' |

import { Print } from '@pit-frontend-framework/utils';

Print('#print-area');
Print(tableRef.value.$el, { noPrint: '.no-print,.action-bar' });

createPrintContent(target, options?)

仅生成打印 HTML 字符串(含样式快照),不触发打印。适用于自定义打印逻辑。

  • 返回值string

MyPrint(target, options?)

Print() 的别名(旧版兼容)。


十六、事件总线 emitter

基于 mitt,提供类型安全的全局事件总线。

import { emitter, createEmitter } from '@pit-frontend-framework/utils';

// 使用全局单例
emitter.on('refresh', () => { /* 刷新列表 */ });
emitter.emit('refresh');
emitter.off('refresh', handler);

// 创建独立实例
const myEmitter = createEmitter();

十七、跨标签广播 broadcastService

基于 BroadcastChannel API,实现同域多个浏览器标签之间的双向通信。

getBroadcastService()

获取默认的广播服务实例(频道名:'app-channel')。

BroadcastService 方法

| 方法 | 签名 | 说明 | | :--- | :--- | :--- | | on<T> | (eventType, handler) => () => void | 注册监听,返回取消函数 | | once<T> | (eventType, handler) => void | 注册一次性监听 | | off | (eventType, handler) => void | 移除监听 | | postMessage<T> | (eventType, data?, triggerSelf?) => void | 广播事件(默认同时触发自身) | | close | () => void | 关闭频道,释放资源 |

import { getBroadcastService } from '@pit-frontend-framework/utils';
import { onUnmounted } from 'vue';

const broadcast = getBroadcastService();

// 监听登出事件
const off = broadcast.on('logout', () => {
  router.push('/login');
});

// 广播登出(通知所有标签)
broadcast.postMessage('logout');

// 组件卸载时移除监听
onUnmounted(() => off());

十八、国际化 i18n

locale(instance)

注入 vue-i18n 实例,同时合并内置中英文语言包(不覆盖宿主已有翻译)。

// main.ts
import { locale } from '@pit-frontend-framework/utils';
import i18n from '@/i18n';

locale(i18n);
app.use(i18n);

t(key, fallback?)

翻译 key,优先使用已注入的 i18n,降级到内置语言包(中文)。

import { t } from '@pit-frontend-framework/utils';

t('validate.longitude', '请输入正确的经度值');

getI18nInstance() / setI18nInstance(instance?)

获取/设置当前 i18n 实例,setI18nInstance(undefined) 同时重置消息解析器。


十九、JWKS 加密 jwks

getJwks(value, jwksPath, options?)

使用 RSA 公钥(JWKS 协议)加密字符串,常用于登录密码加密。

| 参数 | 类型 | 说明 | | :--- | :--- | :--- | | value | string | 待加密的值(如明文密码) | | jwksPath | string | JWKS endpoint URL | | options.kid | string | 指定 kid(覆盖全局配置) | | options.fetcher | (url) => Promise<Response> | 自定义 fetch 函数(测试/代理) | | options.jwks | { keys: JwksKey[] } | 预置 JWKS 数据(跳过网络请求) |

  • 返回值Promise<string> — RSA 加密后的密文
import { getJwks, setJwksConfig, DEFINE_JWKS_PATH, DEFINE_JWKS_KID } from '@pit-frontend-framework/utils';

// 全局配置 kid(只需执行一次)
setJwksConfig({ kid: DEFINE_JWKS_KID });

const encryptedPassword = await getJwks(password, DEFINE_JWKS_PATH);

二十、本地缓存工具 localCache

URL 参数解析

| 函数 | 签名 | 说明 | | :--- | :--- | :--- | | getQueryString | () => Record<string, string> | 解析当前页面 URL 全部查询参数 | | getKeyByUrl | (key: string) => string \| Record<string, string> | 获取单个查询参数值,key 为空则返回全部 |

常用 localStorage 读取

| 函数 | 签名 | 说明 | | :--- | :--- | :--- | | getProjectId | () => string \| Record<string, string> | 从 URL 取 projectId | | getMajorId | () => string \| Record<string, string> | 从 URL 取 majorId | | getUserId | () => string | 从 localStorage 取 userId | | getBidId | () => string | 从 localStorage 取 bidId | | getTaskStatus | () => string | 从 localStorage 取 taskStatus |


二十一、滚动工具 scroll

scrollTo(to, duration?, callback?)

平滑滚动到页面指定位置(easeInOutQuad 缓动)。

| 参数 | 类型 | 默认值 | 说明 | | :--- | :--- | :--- | :--- | | to | number | — | 目标 scrollTop 值(px) | | duration | number | 300 | 动画时长(ms),0 为立即跳转 | | callback | () => void | — | 滚动完成回调 |

import { scrollTo } from '@pit-frontend-framework/utils';

scrollTo(0, 400, () => console.log('已滚动到顶部'));

二十二、表格列宽 tableSize

createTableSize(size?)

根据表格密度生成列宽和对齐配置常量。

| 参数 | 类型 | 说明 | | :--- | :--- | :--- | | size | 'default' \| 'large' \| 'small' | 表格密度,默认 'default' |

  • 返回值TableSizeType,包含 DATE_WIDTHOPERATION_ONE_WIDTH 等预设列宽常量。

TABLE_SIZE(全局单例)

默认密度的表格列宽单例,直接引入使用:

import { TABLE_SIZE } from '@pit-frontend-framework/utils';

// main.ts 中挂载到全局属性
app.config.globalProperties.$TABLE_SIZE = TABLE_SIZE;

在模板中:

<el-table-column label="日期" :width="$TABLE_SIZE.DATE_WIDTH" :align="$TABLE_SIZE.DATE_ALIGN" />

二十三、通用校验 validate

| 函数 | 签名 | 说明 | | :--- | :--- | :--- | | isExternal | (path) => boolean | 是否为外部链接(http/https/mailto/tel) | | validURL | (url) => boolean | 是否为合法 URL | | validEmail | (email) => boolean | 是否为合法邮箱 | | isString | (val) => val is string | 类型守卫:string | | isArray | (val) => val is unknown[] | 类型守卫:array | | islongitude | (rule, value, callback) | el-form-item 经度校验(-180 ~ 180) | | islatitude | (rule, value, callback) | el-form-item 纬度校验(-90 ~ 90) |

import { islongitude, islatitude } from '@pit-frontend-framework/utils';

const rules = {
  longitude: [{ validator: islongitude }],
  latitude:  [{ validator: islatitude }],
};

二十四、页面工具 page

getPageTitle(routeKey?, pageTitle?)

构建 "页面名称 - 应用标题" 格式的浏览器标签标题(常用于路由守卫)。

import { getPageTitle } from '@pit-frontend-framework/utils';

// 在路由守卫中
document.title = getPageTitle(undefined, route.meta.title as string);

setDefaultAppTitle(title) / setAppTitleResolver(fn)

自定义默认应用标题或通过解析函数动态获取(如从 store 读取)。


二十五、组件安装 install

withInstall<T>(component, alias?)

为 Vue 组件添加 install 方法,使其可以 app.use() 注册。

import { withInstall } from '@pit-frontend-framework/utils';
import MyComp from './MyComp.vue';

export const MyComponent = withInstall(MyComp);
// app.use(MyComponent) 或 app.component('MyComp', MyComponent)

definePropType<T>(val)

类型安全的 PropType<T> 辅助函数,避免 as PropType<T> 硬转型。


二十六、pit 业务集合 pit

聚合权限、流程、存储等常用操作的业务工具对象,对应旧版 pit-business-utils

import { pit } from '@pit-frontend-framework/utils';

// 权限
pit.hasP('module:list');
pit.hasBtnP('btn_add');
pit.hasFormP('field_name');
pit.adminAuthority();
pit.isProjectManager();

// 流程:根据审批状态和 writeable 标志判断是否可编辑
pit.hasFlow(params, hasFlowFlag);

// 数字格式化
pit.formatFloat('1234.567', 2);
pit.amountThousandsConversion(1234567.89);  // '1,234,567.89'

// 日期
pit.toDate(new Date(), 'yyyy-MM-dd');
pit.dateFormat(date, 'YYYY-MM-DD');
pit.dateDiff('2026-01-01', '2026-04-29');   // 118

// 树
pit.treeToArray(treeData);
pit.arrayToTree(flatData);
pit.iterationArr(treeData, (node) => { /* ... */ });

// 文件
pit.formatFileSize(1048576);  // '1.00 MB'
pit.getBlobFileName(response);

pit.hasCode 预置按钮编码常量:

btn_add / btn_edit / btn_detail / btn_remove / btn_batchRemove / btn_copy / btn_upload / btn_download / btn_more / btn_grading / btn_password / btn_menu / btn_relation / btn_batchXZ / btn_class / btn_reduction / btn_del / btn_autoSC / btn_batchFB / btn_sum / btn_unlock / btn_estimate


二十七、全局常量 constants

| 常量 | 类型 | 说明 | | :--- | :--- | :--- | | IS_OK | '00000' | 接口成功响应码 | | BIDTYPE.JL | 'JL' | 监理标 | | BIDTYPE.SG | 'SG' | 施工标 | | BIDTYPE.SJ | 'SJ' | 设计标 | | BIDTYPE.ZX | 'ZX' | 咨询标 |

import { IS_OK, BIDTYPE } from '@pit-frontend-framework/utils';

if (response.code === IS_OK) {
  // 请求成功
}

最佳实践:main.ts 启动序列

import { createApp } from 'vue';
import {
  initAppConfigFromViteEnv,
  setRouteResolver,
  setPermissionContext,
  locale,
  setRequestHooks,
} from '@pit-frontend-framework/utils';
import router from '@/router';
import i18n from '@/i18n';
import { useUserStore } from '@/store';

// 1. 最先初始化配置(其他模块依赖此步骤)
initAppConfigFromViteEnv(import.meta.env);

// 2. 注入路由上下文
setRouteResolver(() => router.currentRoute.value);

// 3. 注入权限上下文(惰性解析,pinia 初始化后安全调用)
setPermissionContext({
  getPermissionList: () => useUserStore().permissionList,
  getModelId: () => String(router.currentRoute.value.meta.modelId ?? ''),
});

const app = createApp(App);
setupStore(app);
app.use(router);
app.use(i18n);

// 4. 注入 i18n 实例(合并内置语言包)
locale(i18n);

app.mount('#app');

Peer Dependencies

| 包 | 版本 | 说明 | | :--- | :--- | :--- | | vue | ^3.0.0 | Vue 3 核心 | | axios | ^1.15.0 | HTTP 请求 | | dayjs | ^1.11.1 | 日期处理 | | mitt | ^3.0.0 | 事件总线 | | jsrsasign | ^10.9.0 | JWKS 加密(按需) | | qs | ^6.11.2 | 参数序列化 | | lodash-es | ^4.17.21 | 部分工具函数 |