From 8f8f3481ff610962aa6345ea03bc61e439f8f68a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=83=E8=B4=A7?= <252048765@qq.com> Date: Sun, 13 Jul 2025 09:08:12 +0800 Subject: [PATCH] =?UTF-8?q?refactor(web-ele):=20=E7=A7=BB=E9=99=A4?= =?UTF-8?q?=E6=9C=AA=E4=BD=BF=E7=94=A8=E7=9A=84=E5=B7=A5=E5=85=B7=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除了 utils/index.ts 中未使用的树处理和类型判断函数 - 更新了相关文件中的导入路径 - 优化了代码结构,提高了代码的可读性和维护性 --- apps/web-ele/src/utils/index.ts | 2 - apps/web-ele/src/utils/is.ts | 117 ----- apps/web-ele/src/utils/tree.ts | 440 ------------------ .../mall/product/spu/components/info-form.vue | 2 +- .../mall/product/spu/components/sku-list.vue | 3 +- .../src/components/json-viewer/style.scss | 2 +- .../src/components/resize/resize.vue | 2 +- .../src/widgets/theme-toggle/theme-button.vue | 4 +- 8 files changed, 6 insertions(+), 566 deletions(-) delete mode 100644 apps/web-ele/src/utils/is.ts delete mode 100644 apps/web-ele/src/utils/tree.ts diff --git a/apps/web-ele/src/utils/index.ts b/apps/web-ele/src/utils/index.ts index 162976e7a..b29690876 100644 --- a/apps/web-ele/src/utils/index.ts +++ b/apps/web-ele/src/utils/index.ts @@ -5,6 +5,4 @@ export * from './formCreate'; export * from './rangePickerProps'; export * from './routerHelper'; export * from './validator'; -export * from './tree'; -export * from './is'; export * from './bean'; diff --git a/apps/web-ele/src/utils/is.ts b/apps/web-ele/src/utils/is.ts deleted file mode 100644 index cd2dcc376..000000000 --- a/apps/web-ele/src/utils/is.ts +++ /dev/null @@ -1,117 +0,0 @@ -// copy to vben-admin - -const toString = Object.prototype.toString - -export const is = (val: unknown, type: string) => { - return toString.call(val) === `[object ${type}]` -} - -export const isDef = (val?: T): val is T => { - return typeof val !== 'undefined' -} - -export const isUnDef = (val?: T): val is T => { - return !isDef(val) -} - -export const isObject = (val: any): val is Record => { - return val !== null && is(val, 'Object') -} - -export const isEmpty = (val: any): boolean => { - if (val === null || val === undefined || typeof val === 'undefined') { - return true - } - if (isArray(val) || isString(val)) { - return val.length === 0 - } - - if (val instanceof Map || val instanceof Set) { - return val.size === 0 - } - - if (isObject(val)) { - return Object.keys(val).length === 0 - } - - return false -} - -export const isDate = (val: unknown): val is Date => { - return is(val, 'Date') -} - -export const isNull = (val: unknown): val is null => { - return val === null -} - -export const isNullAndUnDef = (val: unknown): val is null | undefined => { - return isUnDef(val) && isNull(val) -} - -export const isNullOrUnDef = (val: unknown): val is null | undefined => { - return isUnDef(val) || isNull(val) -} - -export const isNumber = (val: unknown): val is number => { - return is(val, 'Number') -} - -export const isPromise = (val: unknown): val is Promise => { - return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch) -} - -export const isString = (val: unknown): val is string => { - return is(val, 'String') -} - -export const isFunction = (val: unknown): val is Function => { - return typeof val === 'function' -} - -export const isBoolean = (val: unknown): val is boolean => { - return is(val, 'Boolean') -} - -export const isRegExp = (val: unknown): val is RegExp => { - return is(val, 'RegExp') -} - -export const isArray = (val: any): val is Array => { - return val && Array.isArray(val) -} - -export const isWindow = (val: any): val is Window => { - return typeof window !== 'undefined' && is(val, 'Window') -} - -export const isElement = (val: unknown): val is Element => { - return isObject(val) && !!val.tagName -} - -export const isMap = (val: unknown): val is Map => { - return is(val, 'Map') -} - -export const isServer = typeof window === 'undefined' - -export const isClient = !isServer - -export const isUrl = (path: string): boolean => { - const reg = - /(((^https?:(?:\/\/)?)(?:[-:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&%@.\w_]*)#?(?:[\w]*))?)$/ - return reg.test(path) -} - -export const isDark = (): boolean => { - return window.matchMedia('(prefers-color-scheme: dark)').matches -} - -// 是否是图片链接 -export const isImgPath = (path: string): boolean => { - return /(https?:\/\/|data:image\/).*?\.(png|jpg|jpeg|gif|svg|webp|ico)/gi.test(path) -} - -export const isEmptyVal = (val: any): boolean => { - return val === '' || val === null || val === undefined -} diff --git a/apps/web-ele/src/utils/tree.ts b/apps/web-ele/src/utils/tree.ts deleted file mode 100644 index 1d6adf2a8..000000000 --- a/apps/web-ele/src/utils/tree.ts +++ /dev/null @@ -1,440 +0,0 @@ -interface TreeHelperConfig { - id: string; - children: string; - pid: string; -} - -const DEFAULT_CONFIG: TreeHelperConfig = { - id: 'id', - children: 'children', - pid: 'pid', -}; -export const defaultProps = { - children: 'children', - label: 'name', - value: 'id', - isLeaf: 'leaf', - emitPath: false, // 用于 cascader 组件:在选中节点改变时,是否返回由该节点所在的各级菜单的值所组成的数组,若设置 false,则只返回该节点的值 -}; -interface Fn { - (...arg: T[]): T; -} - -const getConfig = (config: Partial) => - Object.assign({}, DEFAULT_CONFIG, config); - -// tree from list -export const listToTree = ( - list: any[], - config: Partial = {}, -): T[] => { - const conf = getConfig(config) as TreeHelperConfig; - const nodeMap = new Map(); - const result: T[] = []; - const { id, children, pid } = conf; - - for (const node of list) { - node[children] = node[children] || []; - nodeMap.set(node[id], node); - } - for (const node of list) { - const parent = nodeMap.get(node[pid]); - (parent ? parent.children : result).push(node); - } - return result; -}; - -export const treeToList = ( - tree: any, - config: Partial = {}, -): T => { - config = getConfig(config); - const { children } = config; - const result: any = [...tree]; - for (let i = 0; i < result.length; i++) { - if (!result[i][children!]) continue; - result.splice(i + 1, 0, ...result[i][children!]); - } - return result; -}; - -export const findNode = ( - tree: any, - func: Fn, - config: Partial = {}, -): T | null => { - config = getConfig(config); - const { children } = config; - const list = [...tree]; - for (const node of list) { - if (func(node)) return node; - node[children!] && list.push(...node[children!]); - } - return null; -}; - -export const findNodeAll = ( - tree: any, - func: Fn, - config: Partial = {}, -): T[] => { - config = getConfig(config); - const { children } = config; - const list = [...tree]; - const result: T[] = []; - for (const node of list) { - func(node) && result.push(node); - node[children!] && list.push(...node[children!]); - } - return result; -}; - -export const findPath = ( - tree: any, - func: Fn, - config: Partial = {}, -): T | T[] | null => { - config = getConfig(config); - const path: T[] = []; - const list = [...tree]; - const visitedSet = new Set(); - const { children } = config; - while (list.length) { - const node = list[0]; - if (visitedSet.has(node)) { - path.pop(); - list.shift(); - } else { - visitedSet.add(node); - node[children!] && list.unshift(...node[children!]); - path.push(node); - if (func(node)) { - return path; - } - } - } - return null; -}; - -export const findPathAll = ( - tree: any, - func: Fn, - config: Partial = {}, -) => { - config = getConfig(config); - const path: any[] = []; - const list = [...tree]; - const result: any[] = []; - const visitedSet = new Set(), - { children } = config; - while (list.length) { - const node = list[0]; - if (visitedSet.has(node)) { - path.pop(); - list.shift(); - } else { - visitedSet.add(node); - node[children!] && list.unshift(...node[children!]); - path.push(node); - func(node) && result.push([...path]); - } - } - return result; -}; - -export const filter = ( - tree: T[], - func: (n: T) => boolean, - config: Partial = {}, -): T[] => { - config = getConfig(config); - const children = config.children as string; - - function listFilter(list: T[]) { - return list - .map((node: any) => ({ ...node })) - .filter((node) => { - node[children] = node[children] && listFilter(node[children]); - return func(node) || (node[children] && node[children].length); - }); - } - - return listFilter(tree); -}; - -export const forEach = ( - tree: T[], - func: (n: T) => any, - config: Partial = {}, -): void => { - config = getConfig(config); - const list: any[] = [...tree]; - const { children } = config; - for (let i = 0; i < list.length; i++) { - // func 返回true就终止遍历,避免大量节点场景下无意义循环,引起浏览器卡顿 - if (func(list[i])) { - return; - } - children && - list[i][children] && - list.splice(i + 1, 0, ...list[i][children]); - } -}; - -/** - * @description: Extract tree specified structure - */ -export const treeMap = ( - treeData: T[], - opt: { children?: string; conversion: Fn }, -): T[] => { - return treeData.map((item) => treeMapEach(item, opt)); -}; - -/** - * @description: Extract tree specified structure - */ -export const treeMapEach = ( - data: any, - { children = 'children', conversion }: { children?: string; conversion: Fn }, -) => { - const haveChildren = - Array.isArray(data[children]) && data[children].length > 0; - const conversionData = conversion(data) || {}; - if (haveChildren) { - return { - ...conversionData, - [children]: data[children].map((i: number) => - treeMapEach(i, { - children, - conversion, - }), - ), - }; - } else { - return { - ...conversionData, - }; - } -}; - -/** - * 递归遍历树结构 - * @param treeDatas 树 - * @param callBack 回调 - * @param parentNode 父节点 - */ -export const eachTree = (treeDatas: any[], callBack: Fn, parentNode = {}) => { - treeDatas.forEach((element) => { - const newNode = callBack(element, parentNode) || element; - if (element.children) { - eachTree(element.children, callBack, newNode); - } - }); -}; - -/** - * 构造树型结构数据 - * @param {*} data 数据源 - * @param {*} id id字段 默认 'id' - * @param {*} parentId 父节点字段 默认 'parentId' - * @param {*} children 孩子节点字段 默认 'children' - */ -export const handleTree = ( - data: any[], - id?: string, - parentId?: string, - children?: string, -) => { - if (!Array.isArray(data)) { - console.warn('data must be an array'); - return []; - } - const config = { - id: id || 'id', - parentId: parentId || 'parentId', - childrenList: children || 'children', - }; - - const childrenListMap: Record = {}; - const nodeIds: Record = {}; - const tree: any[] = []; - - for (const d of data) { - const parentId = d[config.parentId]; - if (childrenListMap[parentId] == null) { - childrenListMap[parentId] = []; - } - nodeIds[d[config.id]] = d; - childrenListMap[parentId].push(d); - } - - for (const d of data) { - const parentId = d[config.parentId]; - if (nodeIds[parentId] == null) { - tree.push(d); - } - } - - for (const t of tree) { - adaptToChildrenList(t); - } - - function adaptToChildrenList(o: any) { - if (childrenListMap[o[config.id]] !== null) { - o[config.childrenList] = childrenListMap[o[config.id]]; - } - if (o[config.childrenList]) { - for (const c of o[config.childrenList]) { - adaptToChildrenList(c); - } - } - } - - return tree; -}; - -/** - * 构造树型结构数据 - * @param {*} data 数据源 - * @param {*} id id字段 默认 'id' - * @param {*} parentId 父节点字段 默认 'parentId' - * @param {*} children 孩子节点字段 默认 'children' - * @param {*} rootId 根Id 默认 0 - */ -// @ts-ignore -export const handleTree2 = (data, id, parentId, children, rootId) => { - id = id || 'id'; - parentId = parentId || 'parentId'; - // children = children || 'children' - rootId = - rootId || - Math.min( - ...data.map((item: any) => { - return item[parentId]; - }), - ) || - 0; - // 对源数据深度克隆 - const cloneData = JSON.parse(JSON.stringify(data)); - // 循环所有项 - const treeData = cloneData.filter((father: any) => { - const branchArr = cloneData.filter((child: any) => { - // 返回每一项的子级数组 - return father[id] === child[parentId]; - }); - branchArr.length > 0 ? (father.children = branchArr) : ''; - // 返回第一层 - return father[parentId] === rootId; - }); - return treeData !== '' ? treeData : data; -}; - -/** - * 校验选中的节点,是否为指定 level - * - * @param tree 要操作的树结构数据 - * @param nodeId 需要判断在什么层级的数据 - * @param level 检查的级别, 默认检查到二级 - * @return true 是;false 否 - */ -export const checkSelectedNode = ( - tree: any[], - nodeId: any, - level = 2, -): boolean => { - if ( - typeof tree === 'undefined' || - !Array.isArray(tree) || - tree.length === 0 - ) { - console.warn('tree must be an array'); - return false; - } - - // 校验是否是一级节点 - if (tree.some((item) => item.id === nodeId)) { - return false; - } - - // 递归计数 - let count = 1; - - // 深层次校验 - function performAThoroughValidation(arr: any[]): boolean { - count += 1; - for (const item of arr) { - if (item.id === nodeId) { - return true; - } else if ( - typeof item.children !== 'undefined' && - item.children.length !== 0 - ) { - if (performAThoroughValidation(item.children)) { - return true; - } - } - } - return false; - } - - for (const item of tree) { - count = 1; - if (performAThoroughValidation(item.children)) { - // 找到后对比是否是期望的层级 - if (count >= level) { - return true; - } - } - } - - return false; -}; - -/** - * 获取节点的完整结构 - * @param tree 树数据 - * @param nodeId 节点 id - */ -export const treeToString = (tree: any[], nodeId: any) => { - if ( - typeof tree === 'undefined' || - !Array.isArray(tree) || - tree.length === 0 - ) { - console.warn('tree must be an array'); - return ''; - } - // 校验是否是一级节点 - const node = tree.find((item) => item.id === nodeId); - if (typeof node !== 'undefined') { - return node.name; - } - let str = ''; - - function performAThoroughValidation(arr: any[]) { - for (const item of arr) { - if (item.id === nodeId) { - str += ` / ${item.name}`; - return true; - } else if ( - typeof item.children !== 'undefined' && - item.children.length !== 0 - ) { - str += ` / ${item.name}`; - if (performAThoroughValidation(item.children)) { - return true; - } - } - } - return false; - } - - for (const item of tree) { - str = `${item.name}`; - if (performAThoroughValidation(item.children)) { - break; - } - } - return str; -}; diff --git a/apps/web-ele/src/views/mall/product/spu/components/info-form.vue b/apps/web-ele/src/views/mall/product/spu/components/info-form.vue index c5bd3d446..815102024 100644 --- a/apps/web-ele/src/views/mall/product/spu/components/info-form.vue +++ b/apps/web-ele/src/views/mall/product/spu/components/info-form.vue @@ -1,6 +1,6 @@