@highmark/crm-utils
v0.0.36
Published
```shell npm i @highmark/crm-utils ```
Downloads
55
Readme
安装
npm i @highmark/crm-utils引入
import utils from '@highmark/crm-utils'工具类 - tool
tool这块引用了 lodash 和 vueuse, 如果当前项目需要 lodash 和 vueuse 别的方法则单独安装这两个包, 否则会出现幽灵依赖的问题
cloneDeep (lodash)
debounce (lodash)
throttle (lodash)
isEqual (lodash)
pick (lodash)
pickBy (lodash)
isNumber (lodash)
chunk (lodash)
useDebounceFn ( @vueuse/core )
useThrottleFn ( @vueuse/core )
delay(time=30) // 延迟
findNodeByName // 根据 name 获取对应树的节点 (适用于菜单树)
calculateStringLength(input:string): number // 计算当前字符串长度, 如果汉字则为2, 如果是英文则为1, 如果没有值则为0
vue element
isNonEmptySlot(slots, slotKey) // 查看指定插槽内是否有元素
isCommentType // 判断当前目标是否是注释类型 (用于判断虚拟节点)
getPaddingByElement. // 获取元素的padding值
interface IGetPaddingByElement { (element: HTMLElement): GetPaddingByElementResultType } type GetPaddingByElementResultType = { top: number right: number bottom: number left: number }findParentsWithClass // 找到当前dom节点父级包含
className的节点interface IFindParentsWithClass { // className: 类名不用.开头 (el: HTMLElement, className: string): HTMLElement[] }
处理 url 类. - url
replaceCurrentUrl // 替换当前 url
paramObjectToQueryString // 将对象转换为参数字符串的工具方法, 返回结果 '?name=aa&age=19'
parseQueryString(urlStr) // 解析 url 参数
parseUrl // 根据 url 获取参数对象, 返回
{ hash: '#...', hostname: 'https://...' , params: { k: v, ... }}mergeFormDataByCurrentUrl( {formData} ) // 融合当前 url 的 formData 参数 (注意是放在当前模块 formData 的默认赋值的上面还是下面, 这个循序会影响相同属性是否会覆盖)
toPageCarryFormData({ name, formData }) // 跳转页面并携带 formdata 参数, 会对 formData 进行编码
时间 - time
dayjs改造
subDate // 获取时间 a-b 的值, 参数(Date1, Date2)
forMatterDate(date, format = 'YYYY-MM-DD HH:mm:ss') // 转换时间格式
get30PreDay // 获取 30 天前的时间
getCurrentDate(format = 'YYYY-MM-DD HH:mm:ss') // 获取当前时间
get30PreDay // 获取三十天前的时间
getPreFirstYearAndCurrentDate(format = 'YYYY-MM-DD HH:mm:ss') // 获取当前时间的前一年时间和当前时间, 返回 [ 前一年时间, 当前时间 ]
getFirstDayOfCurrentMonth(format = 'YYYY-MM-DD HH:mm:ss') // 获取当前月的第一天
getCurrentTimestamp // 获取当前时间戳(以毫秒为单位)
处理业务类 - yewu
😭refreshClientId // 刷新 clientId, 防止重复请求
formatUserAndOrg // 格式化对象为 用户带部门的对象(大多用于反显), 参数: { userName, userId, orgId, orgName }
😭openDetailPopup // 打开详情页 ( 传参 { componentName, componentTitle } )
😭refreshAllTabCount // 通过事件总线的方式, 刷新详情中 tabs 组件的 count
formatUserAndOrgAndNodeId({ userName, userId, orgId, orgName }) // 格式化对象为 用户带部门的对象, 返回
{ name, id, orgs, _node_id }formatNmyUserAndOrgAndNodeId_V2({ orgId, orgName, userId, userName }) // (nmy组织架构组件专用) 格式化对象为 用户带部门的对象, 返回
{ userName, userId, orgId, orgName, id: '用户id!部门id' }parseUserAndOrg // 将员工对象格式化为 { userName, userId, orgId, orgName }
数学类 - math
addNums // 计算: 加
subNums // 计算: 减
mulNums // 计算: 乘
divNums // 计算: 除
round // 四舍五入
isNumberStrict // 判断是否是数字 (必须数字类型, 严格模式)
isNumberLoose // 判断是否能转换为数字 (任何类型, 宽松模式)
getFixed // 解析数字, 补充后两位
getFixedNumber // 解析为 最多保留两位小数的数字 (常用于验证: 比较金额, 数量等), 返回数字类型
handleOnlyAllowNumber // 只能输入数字和. (用于 input 组件的监听限制)
isZero // 判断当前是否是 0 或者'0'
truncateDecimal( value, 保留几位 ) // 将数字保留小数 ( 向下取整, 不会约等于 )
truncateDecimalStr( value, 保留几位 ) // 值为字符串
generateRandomCode 获取随机字符串和数字 (去掉了 0 和o 和 I 和 1, l, 以免歧义)
isSame 比较两个数字是否相等
转换 - tran
tranId // 转换 id, 如果是正常的 id, 则返回原值, 如果是空或者下面的 id, 则返回 null, 也会判断
00000000-0000-0000-0000-000000000000tranDate // 转换时间, 如果是正常的时间, 则返回原值, 如果是空或者下面的 id, 则返回 null, 也会判断
1900-01-01 00:00:00tranNumber // 转换为数字, Infinity 或者 NaN 或者 null 或者'' 或者 NaN 或者 undefined 都返回 0
parseValueJudgeEmpty // 判断值是否为空, 如果为空返回 '-'
tranTipInnerHtml(...args) // 生成tips 的html片段
replaceInvalidValuesWithNull(value) // 替换无效值为null, 目标为对象或数组 (用于格式化获取请求回来的数据, 避免出现脏数据)(深度克隆)
校验 - validate
isNonEmptyArray // 检查数组是否非空且长度大于 1
getFormRulesByCurrentEnv // 根据当前环境(移动端/pc)获取验证规则
- mobile: { // 数字: 支持验证负数, 支持字符串格式 isNumber // 金额: 数字类型 && 不等于 0 isNonEmptyNumber // 检查数组是否非空且长度大于 1 isNonEmptyArray // 必须填写 requiredInput // 必须选择 requiredSelect // 必须上传 (目标数组, 报错信息) requiredUploadByTarget(附件数组,'报错消息') // 自定义规则 (如果有错误直接返回报错信息, 没有错误不用管) customValidator({ cb:(value)=>{ return '报错信息' } }) }
- pc: { // 数字: 支持验证负数, 支持字符串格式 isNumber // 金额: 数字类型 && 不能为 0 isNonEmptyNumber, // 检查数组是否非空且长度大于 1 isNonEmptyArray, // 必须填写 requiredInput, // 必须选择 requiredSelect, // 必须上传 requiredUpload, // 自定义规则 (如果有错误直接返回报错信息, 没有错误不用管) customValidator({ cb:(value)=>{ return '报错信息' } }) }
file 文件处理
getMd5ByFile // 文件转换为 MD5
blobTOBase64 // blob 转 base64
blobToFile // blob 转文件
urlTOBlob // url 转 blob
urlTOFile // url 转 file
fileTOBase64 // file 转 base64
fileTOBlob // file 转 blob
base64TOBlob // base64 转 Blob
elementTOImage // img 元素转 base64
permission 权限处理
import { permission } from '../../config/permission'
isDisabled // 当前是否是禁用( 响应式 ), 使用: isDisabled(permission.BTN_DETAIL)
// 计算属性 ComputedRef<Array<string>> 或者 Ref<Array<string> >都可以 type permissionListProxyType = { value: Array<string> } interface IIsDisabled { (action: string, permissionListProxy: permissionListProxyType): Ref<boolean> }isEnabled // 当前是否是启用( 响应式 ), 使用: isEnabled(permission.BTN_DETAIL)
client 客户端相关 - client
- isMobile
- isSafari
- useIsMobileHook // 返回 { isMobileRef }
- isSafari: isSafariType // 当前是否是Safari浏览器
- isPc: isMobileRefType // 当前是否是PC端
- isDing: isDingType // 当前是否是钉钉浏览器
vite
- openEditDetailComponent
options: {
viewsModuleName?: string // 模块名称
viewModuleId?: string // 模块id
detailComponentName?: string // 详情页组件名称
destroyPropName?: string // 组件销毁的props属性名 (对应props值为函数类型)
routeMapper?: InstanceType<typeof Map<number, string>> // 模块id和路由映射
methodMapper: InstanceType<typeof Map<string, any>> // Map<触发方法名, 传参>
metaGlobModules: any // import.meta.glob
}二次封装
import utils from '@highmark/crm-utils'
/**
* 创建一个映射,用于存储路由ID和对应的页面路径
*/
const routeMapper = new Map()
// { 模块id, 模块name }
routeMapper.set(1, 'about') // 注意 模块name为views内的模块id, 这里建议与路由的name一致
/**
* 打开详情页功能。
* 用于加载并显示指定的详情组件,支持组件名称和组件ID映射的方式。
* @param {Object} param 一个包含多个配置选项的对象。
* @param {Map<string, any>} param.methodMapper 组件暴露的方法映射 Map<方法名, 传参|null>
* @param {string} param.viewsModuleName 视图模块的名称。
* @param {string} param.viewModuleId 视图模块的ID。
* @param {string} param.detailComponentName 详情组件的名称,默认为"AddAndEdit.vue"。
* @param {string} param.destroyPropName 销毁属性的名称,默认为'destroy'。
*/
export function openAddAndDetail({
exposedMethods,
viewsModuleName,
viewModuleId,
detailComponentName,
destroyPropName
} = {}) {
// 判断当前浏览器环境
const { isMobileRef } = utils.client.useIsMobileHook()
// 根据当前运行环境动态导入所有视图文件以支持路径的通配符匹配
let metaGlobModules = ''
if (isMobileRef.value) {
// 配置 移动端 详情 路径
metaGlobModules = import.meta.glob(`@/views/**/mobile/**/**.vue`)
} else {
// 配置 pc 详情 路径
metaGlobModules = import.meta.glob(`@/views/**/pc/**/**.vue`)
}
// 调用utils工具库中的方法,以打开编辑详情组件,并传入相关配置
utils.vite.openEditDetailComponent({
metaGlobModules,
methodMapper: methodMapper, // new Map(Object.entries({ open: { dataId: '数据id' } }))
viewsModuleName: viewsModuleName,
routeMapper: routeMapper, // 路由映射器,用于解析路由ID到实际路径
viewModuleId: viewModuleId,
detailComponentName: detailComponentName || 'AddAndEdit.vue', // 如果未提供详情组件名称,则默认为"AddAndEdit.vue"
destroyPropName: destroyPropName || 'destroy' // 如果未提供销毁props名称,则默认为'destroy'
})
}使用
openAddAndDetail({
// exposedMethods,
// viewsModuleName,
viewModuleId, // 如果配置了 routeMapper 映射, 直接传入模块id即可弹出详情
// 触发组件暴露方法的映射 Map<方法名, 传参>
methodMapper: new Map(
Object.entries({
// 如果携带数据值为 { dataId, ... }
open: { dataId: '数据详情的id' }
})
)
// detailComponentName,
// destroyPropName
})注意
( 详情页props必须配置 destroy 属性,
必须暴露 open, close 方法,
如弹窗销毁必须触发销毁props.destroy的方法
):
const props = defineProps({
// 销毁
destroy: {
type: Function,
default: null
}
})
const isShow = ref(false)
/**
* 触发销毁prop
**/
const executeDestroyProp = () => {
if (typeof props.destroy === 'function') {
props.destroy()
}
}
const close = () => {
isShow.value = false
// 必须执行触发销毁prop
executeDestroyProp()
}
defineExpose({
open,
close
})公共常量 constant
微服务事件类
utils.constant.microEventTypes
import utils from '@highmark/crm-utils'
// 传向基座
utils.constant.microEventTypes.toBase.OPEN_DETAIL_POPUP
// 传向子模块
utils.constant.microEventTypes.toChild.OPEN_DETAIL_POPUP
// 传向其他兄弟模块
utils.constant.microEventTypes.toSibling.OPEN_DETAIL_POPUP简单描述传递参数
参数说明 陆续补充
/**
* 发送到基组件的事件类型
*/
toBase: {
/**
* 打开详细信息弹窗
* 传参 {
* eventType:string, // 事件类型
* moduleId?:string, // 路由id
* moduleName?:string, // 路由Name
* appid?:string, // 微服务Id
* detailData?:Record<string, any> // 详情对象信息
* }
*/
OPEN_DETAIL_POPUP,
/**
* 刷新待办消息列表数据
* 传参 {
* eventType:string,
* }
*/
REFRESH_TODO_MESSAGE_LIST_DATA,
/**
* token 过期登出
* 传参 {
* eventType:string,
* }
*/
TOKEN_EXPIRES_SIGN_OUT,
/**
* 子模块加载路由成功后通知基座的事件
* 传参 {
* eventType:string,
* }
*/
LOAD_ROUTES_SUCCESS,
/**
* 子模块通知基座已经打开详情;
* 传参 { state: 'on' | 'off' }
*/
SWITCH_CHILDREN_DETAIL_POPUP_STATE
},
/**
* 发送到子组件的事件类型
*/
toChild: {
/**
* 打开详细信息弹窗
* 传参 {
* eventType:string, // 事件类型
* moduleId?:string, // 路由id
* moduleName?:string, // 路由Name
* appid?:string, // 微服务Id
* detailData?:Record<string, any> // 详情对象信息
* }
*/
OPEN_DETAIL_POPUP,
/**
* 用户权限信息
* 传参 {
* eventType:string, // 事件类型
* menus:Array<{ name:string, path:string, children: any[], meta: { appid:string, title:string, type:string, icon:string, ... } }>, // 菜单
* permission: string[], // 按钮权限
* refreshToken: string, // 刷新token
* token: string, // token
* userInfo: Record<string, any> // 用户信息
* refreshTokenFn: 刷新 token 和 refreshToken的方法
* ( 注意: 该方法为异步函数, 返回值 { token, refreshToken } )
* baseRouter, // 基座router路由对象
* }
*/
AUTH_DATA,
/**
* 通知 子模块 更新本地 token 和 refreshToken
* 传参 {
* token, refreshToken
* }
*/
UPDATE_TOKEN_AND_REFRESHTOKEN,
/**
* 通知 子模块 的 keepAlive 路由列表
* 传参 {
* keepAliveList: string[]
* }
*/
UPDATE_KEEP_ALIVE_LIST,
/**
* 通知子模块刷新页面
*/
REFRESH_PAGE
},
/**
* 发送到同级组件的事件类型
*/
toSibling: {
/**
* 打开详细信息弹窗
* 传参 {
* eventType:string, // 事件类型
* moduleId?:string, // 路由id
* moduleName?:string, // 路由Name
* appid?:string, // 微服务Id
* detailData?:Record<string, any> // 详情对象信息
* }
*/
OPEN_DETAIL_POPUP
}子模块获取auth的案例
// 获取用户权限相关信息
const { authData } = initAuthData()
// 可以拿到token, 菜单...等信息
// console.log(authData.token)
// 初始化权限信息
function initAuthData() {
const data = window.microApp.getData() // 返回主应用下发的data数据
let authData // 权限信息
// 判断类型为权限才会赋值
if (data.eventType === crmUtils.constant.microEventTypes.toChild.AUTH_DATA) {
authData = data || {}
}
return {
authData
}
}