diff --git a/web/src/hooks/useBoolean.ts b/web/src/hooks/useBoolean.ts new file mode 100644 index 0000000..1646ffa --- /dev/null +++ b/web/src/hooks/useBoolean.ts @@ -0,0 +1,49 @@ +import { ref, Ref } from "vue"; + +type Resettable = + /** + * 基础形式为一个元组,包含: + * 1. `Ref`:状态引用,可以直接访问和修改状态值 + * 2. `() => void`:切换真假 + * 3. `(value: boolean) => void`:设置状态 + * 4.`() => void`:设置为`true`方法 + * 5.`() => void`:设置为`false`方法 + */ + [Ref, () => void, () => void] & /** + * 同时扩展为一个对象形式,提供以下属性和方法: + * - `loading: Ref`:状态引用,与元组中的第一个元素相同 + * - `startLoading: () => void`:开始加载方法,与元组中的第二个元素相同 + * - `endLoading: () => void`:结束加载方法,与元组中的第三个元素相同 + */ { + /** 加载状态引用 */ + bool: Ref; + toggle: () => void; + setBool: (value: boolean) => void; + setTrue: () => void; + setFalse: () => void; + }; +export default function useBoolean(initValue = false): Resettable { + const bool = ref(initValue); + + function setBool(value: boolean) { + bool.value = value; + } + function setTrue() { + setBool(true); + } + function setFalse() { + setBool(false); + } + function toggle() { + setBool(!bool.value); + } + + // 返回带加载状态引用、开始加载和结束加载方法的扩展数组 + return (Object.assign([bool, toggle, setBool, setTrue, setFalse], { + bool, + toggle, + setBool, + setTrue, + setFalse, + }) as unknown) as Resettable; +} diff --git a/web/src/layout/components/Header/Search.vue b/web/src/layout/components/Header/Search.vue new file mode 100644 index 0000000..05cdee1 --- /dev/null +++ b/web/src/layout/components/Header/Search.vue @@ -0,0 +1,241 @@ + + + diff --git a/web/src/layout/components/Header/index.vue b/web/src/layout/components/Header/index.vue index 3e91bcb..8756836 100644 --- a/web/src/layout/components/Header/index.vue +++ b/web/src/layout/components/Header/index.vue @@ -69,6 +69,7 @@
+ @@ -200,6 +201,8 @@ import { notificationStoreWidthOut } from '@/store/modules/notification'; import { getIcon } from '@/enums/systemMessageEnum'; + import Search from './Search.vue'; + export default defineComponent({ name: 'PageHeader', components: { @@ -208,6 +211,7 @@ ProjectSetting, AsideMenu, SystemMessage, + Search, }, props: { collapsed: { diff --git a/web/src/utils/tree.ts b/web/src/utils/tree.ts new file mode 100644 index 0000000..b67e076 --- /dev/null +++ b/web/src/utils/tree.ts @@ -0,0 +1,97 @@ +/** + * 树形数组转平级 + * @date 2023-01-09 + * @returns {array} + */ +export const tree2FlatArray = (tree: any[], childrenKey: string = "children") => { + return tree.reduce((arr, item) => { + var children = item?.[childrenKey] ?? []; + var obj = item; + delete obj[childrenKey]; + //解构赋值+默认值 + return arr.concat([obj], tree2FlatArray(children)); //children部分进行递归 + }, []); +}; +/** + * 树形数组转对象 + * @date 2023-01-09 + * @returns {object} + */ +export const tree2Objects = ( + tree: any[], + key: string = "id", + childrenKey: string = "children" +) => { + let rows = tree2FlatArray(tree, childrenKey); + let objects = {}; + rows.forEach((item) => { + objects[item[key]] = item; + }); + return objects; +}; + +/** + * 树形菜单数据输出 + * @date 2022-04-20 + * @param {object} data - 数据 + * @param {string} pid="parent_id" - 父类名称 + * @param {string} children="children" - 子类名称 + * @returns {object} + */ +export const treesBy = ( + data: any[], + pid: string = "parent_id", + children: string = "children" +) => { + let map = {}, + val = []; + data.forEach((item) => { + item[children] = []; + map[item.id] = item; + }); + data.forEach((item) => { + const parent = map[item[pid]]; + if (!!parent) { + parent[children].push(item); + } else { + val.push(item); + } + }); + return val; +}; +/** + * 格式化树形菜单,省市区 + * @param {object} org + * @returns {object} + */ +export const mapTree = (org: any, keyId = "v", keyChild = "s", keyName = "n") => { + const haveChildren = + org[keyChild] && Array.isArray(org[keyChild]) && org[keyChild].length > 0; + return { + key: org[keyId], + value: String(org[keyId]), + label: org[keyName], + isLeaf: true, + children: haveChildren ? org[keyChild].map((i) => mapTree(i)) : [], + }; +}; + +/** + * 格式化树形菜单,省市区 + * @param {object} org + * @returns {object} + */ +export const toFlatArray = ( + tree: any[], + parentId: string | number, + keyId: string | number = "key" +) => { + return tree.reduce((t, _) => { + const child = _["children"]; + return [ + ...t, + { [keyId]: _[keyId], parentId }, + ...(child && child.length ? toFlatArray(child, _[keyId]) : []), + ]; + }, []); +};