From f09043205d5bd8cf833e44ab6031332fb08a3312 Mon Sep 17 00:00:00 2001
From: Ben Lin <maobin001@msn.com>
Date: 星期日, 24 三月 2024 11:50:53 +0800
Subject: [PATCH] 一些更新

---
 .gitignore                                 |  225 +++--------------
 packages/types/.eslintrc.js                |    4 
 packages/hooks/build.config.ts             |   10 
 packages/types/src/index.ts                |    1 
 packages/types/build.config.ts             |   10 
 packages/types/src/utils.ts                |   58 ++++
 packages/types/tsconfig.json               |    5 
 README.md                                  |  166 ++++++++++++
 packages/.gitkeep                          |    0 
 .env.development                           |    4 
 packages/hooks/src/useRefs.ts              |   24 +
 packages/hooks/src/index.ts                |    6 
 packages/hooks/src/useAttrs.ts             |   43 +++
 packages/hooks/tsconfig.json               |    5 
 packages/hooks/package.json                |   38 ++
 packages/types/package.json                |   31 ++
 packages/hooks/src/onMountedOrActivated.ts |   25 +
 packages/hooks/.eslintrc.js                |    4 
 packages/hooks/src/useScrollTo.ts          |   60 ++++
 packages/hooks/src/useWindowSizeFn.ts      |   40 +++
 20 files changed, 571 insertions(+), 188 deletions(-)

diff --git a/.env.development b/.env.development
index d8873db..643a419 100644
--- a/.env.development
+++ b/.env.development
@@ -5,14 +5,14 @@
 VITE_PUBLIC_PATH = /
 
 # Basic interface address SPA
-VITE_GLOB_API_URL=http://localhost:9633/api
+VITE_GLOB_API_URL=http://localhost:9528/api
  #VITE_GLOB_API_URL=http://172.18.8.56:9633/api
 # VITE_GLOB_API_URL=http://localhost:9633/api
 #Tsk Interface address
 # VITE_GLOB_TSK_API_URL=http://172.18.8.56:9633/api
 # VITE_GLOB_TSK_API_URL=http://localhost:9633/api
 
-VITE_GLOB_TSK_API_URL=http://localhost:9633/api
+VITE_GLOB_TSK_API_URL=http://localhost:9528/api
 # VITE_GLOB_TSK_API_URL=http://localhost:9527/api
 
 # File upload address锛� optional
diff --git a/.gitignore b/.gitignore
index 1c38a68..76c5f7a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,186 +1,43 @@
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
+node_modules
+.DS_Store
+dist
+.npmrc
+.cache
+.turbo
 
-# User-specific files
+tests/server/static
+tests/server/static/upload
+
+.local
+# local env files
+.env.local
+.env.*.local
+.eslintcache
+
+# VS files
+.vs/
+.sqlite
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor directories and files
+.idea
+# .vscode
 *.suo
-*.user
-*.sln.docstates
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-build/
-bld/
-[Bb]in/
-[Oo]bj/
-
-# Roslyn cache directories
-*.ide/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-#NUNIT
-*.VisualState.xml
-TestResult.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-*_i.c
-*_p.c
-*_i.h
-*.ilk
-*.meta
-*.obj
-*.pch
-*.pdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opensdf
-*.sdf
-*.cachefile
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# JustCode is a .NET coding addin-in
-.JustCode
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-## TODO: Comment the next line if you want to checkin your
-## web deploy settings but do note that will include unencrypted
-## passwords
-*.pubxml
-
-# NuGet Packages
-packages/*
-*.nupkg
-## TODO: If the tool you use requires repositories.config
-## uncomment the next line
-#!packages/repositories.config
-
-# Enable "build/" folder in the NuGet Packages folder since
-# NuGet packages use it for MSBuild targets.
-# This line needs to be after the ignore of the build folder
-# (and the packages folder if the line above has been uncommented)
-!packages/build/
-
-# Windows Azure Build Output
-csx/
-*.build.csdef
-
-# Windows Store app package directory
-AppPackages/
-
-# Others
-sql/
-*.Cache
-ClientBin/
-[Ss]tyle[Cc]op.*
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.pfx
-*.publishsettings
-node_modules/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-
-# SQL Server files
-*.mdf
-*.ldf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-
-# Microsoft Fakes
-FakesAssemblies/
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+/.vs
+/.vscode
+/.github
+/.husky
+/package-lock.json
+/yarn.lock
+package-lock.json
+pnpm-lock.yaml
+.history
\ No newline at end of file
diff --git a/README.md b/README.md
index 617c45a..da318bf 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,166 @@
-## TigerAdmin_2024
+<div align="center"> <a href="https://github.com/anncwb/vue-vben-admin"> <img alt="VbenAdmin Logo" width="200" height="200" src="https://anncwb.github.io/anncwb/images/logo.png"> </a> <br> <br>
 
-閽涙牸BS骞冲彴绠$悊绯荤粺 2024 鐗�
+[![license](https://img.shields.io/github/license/anncwb/vue-vben-admin.svg)](LICENSE)
 
+<h1>Vue vben admin</h1>
+</div>
+
+**English** | [涓枃](./README.zh-CN.md)
+
+## Introduction
+
+Vue Vben Admin is a free and open source middle and back-end template. Using the latest `vue3`, `vite2`, `TypeScript` and other mainstream technology development, the out-of-the-box middle and back-end front-end solutions can also be used for learning reference.
+
+## Feature
+
+- **State of The Art Development**锛歎se front-end front-end technology development such as Vue3/vite2
+- **TypeScript**: Application-level JavaScript language
+- **Theming**: Configurable themes
+- **International**锛欱uilt-in complete internationalization program
+- **Mock Server** Built-in mock data scheme
+- **Authority** Built-in complete dynamic routing permission generation scheme.
+- **Component** Multiple commonly used components are encapsulated twice
+
+## Preview
+
+- [vue-vben-admin](https://vben.vvbin.cn/) - Full version Chinese site
+- [vue-vben-admin-gh-pages](https://anncwb.github.io/vue-vben-admin/) - Full version of the github site
+- [vben-admin-thin-next](https://vben.vvbin.cn/thin/next/) - Simplified Chinese site
+- [vben-admin-thin-gh-pages](https://anncwb.github.io/vben-admin-thin-next/) -Simplified github site
+
+Test account: vben/123456
+
+<p align="center">
+    <img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview1.png">
+    <img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview2.png">
+    <img alt="VbenAdmin Logo" width="100%" src="https://anncwb.github.io/anncwb/images/preview3.png">
+</p>
+
+### Use Gitpod
+
+Open the project in Gitpod (free online dev environment for GitHub) and start coding immediately.
+
+[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/anncwb/vue-vben-admin)
+
+## Documentation
+
+[Document](https://doc.vvbin.cn/)
+
+## Preparation
+
+- [node](http://nodejs.org/) and [git](https://git-scm.com/) - Project development environment
+- [Vite](https://vitejs.dev/) - Familiar with vite features
+- [Vue3](https://v3.vuejs.org/) - Familiar with Vue basic syntax
+- [TypeScript](https://www.typescriptlang.org/) - Familiar with the basic syntax of `TypeScript`
+- [Es6+](http://es6.ruanyifeng.com/) - Familiar with es6 basic syntax
+- [Vue-Router-Next](https://next.router.vuejs.org/) - Familiar with the basic use of vue-router
+- [Ant-Design-Vue](https://2x.antdv.com/docs/vue/introduce-cn/) - ui basic use
+- [Mock.js](https://github.com/nuysoft/Mock) - mockjs basic syntax
+
+## Install and use
+
+- Get the project code
+
+```bash
+git clone https://github.com/anncwb/vue-vben-admin.git
+```
+
+- Installation dependencies
+
+```bash
+cd vue-vben-admin
+
+pnpm install
+
+```
+
+- run
+
+```bash
+pnpm serve
+```
+
+- build
+
+```bash
+pnpm build
+```
+
+## Change Log
+
+[CHANGELOG](./CHANGELOG.zh_CN.md)
+
+## Project
+
+- [vue-vben-admin](https://github.com/anncwb/vue-vben-admin) - full version
+- [vue-vben-admin-thin-next](https://github.com/anncwb/vben-admin-thin-next) - Simplified version
+
+## How to contribute
+
+You are very welcome to join锛乕Raise an issue](https://github.com/anncwb/vue-vben-admin/issues/new/choose) Or submit a Pull Request銆�
+
+**Pull Request:**
+
+1. Fork code!
+2. Create your own branch: `git checkout -b feat/xxxx`
+3. Submit your changes: `git commit -am 'feat(function): add xxxxx'`
+4. Push your branch: `git push origin feat/xxxx`
+5. submit`pull request`
+
+## Git Contribution submission specification
+
+- reference [vue](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md) specification ([Angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular))
+
+  - `feat` Add new features
+  - `fix` Fix the problem/BUG
+  - `style` The code style is related and does not affect the running result
+  - `perf` Optimization/performance improvement
+  - `refactor` Refactor
+  - `revert` Undo edit
+  - `test` Test related
+  - `docs` Documentation/notes
+  - `chore` Dependency update/scaffolding configuration modification etc.
+  - `workflow` Workflow improvements
+  - `ci` Continuous integration
+  - `types` Type definition file changes
+  - `wip` In development
+
+## Related warehouse
+
+If these plugins are helpful to you, you can give a star support
+
+- [vite-plugin-mock](https://github.com/anncwb/vite-plugin-mock) - Used for local and development environment data mock
+- [vite-plugin-html](https://github.com/anncwb/vite-plugin-html) - Used for html template conversion and compression
+- [vite-plugin-compression](https://github.com/anncwb/vite-plugin-compression) - Used to pack input .gz|.brotil files
+- [vite-plugin-svg-icons](https://github.com/anncwb/vite-plugin-svg-icons) - Used to quickly generate svg sprite
+
+## Browser support
+
+The `Chrome 80+` browser is recommended for local development
+
+Support modern browsers, not IE
+
+| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt=" Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
+| :-: | :-: | :-: | :-: | :-: |
+| not support | last 2 versions | last 2 versions | last 2 versions | last 2 versions |
+
+## Maintainer
+
+[@Vben](https://github.com/anncwb)
+
+## Donate
+
+If you think this project is helpful to you, you can help the author buy a cup of coffee to show your support!
+
+![donate](https://anncwb.github.io/anncwb/images/sponsor.png)
+
+<a style="display: block;width: 100px;height: 50px;line-height: 50px; color: #fff;text-align: center; background: #408aed;border-radius: 4px;" href="https://www.paypal.com/paypalme/cvvben">Paypal Me</a>
+
+## Discord
+
+- [github discussions](https://github.com/anncwb/vue-vben-admin/discussions)
+- [Discord](https://discord.gg/8GuAdwDhj6)
+
+## License
+
+[MIT 漏 Vben-2020](./LICENSE)
diff --git a/packages/.gitkeep b/packages/.gitkeep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/packages/.gitkeep
diff --git a/packages/hooks/.eslintrc.js b/packages/hooks/.eslintrc.js
new file mode 100644
index 0000000..cd27a19
--- /dev/null
+++ b/packages/hooks/.eslintrc.js
@@ -0,0 +1,4 @@
+module.exports = {
+  root: true,
+  extends: ['@vben/eslint-config/strict'],
+};
diff --git a/packages/hooks/build.config.ts b/packages/hooks/build.config.ts
new file mode 100644
index 0000000..20c8b54
--- /dev/null
+++ b/packages/hooks/build.config.ts
@@ -0,0 +1,10 @@
+import { defineBuildConfig } from 'unbuild';
+
+export default defineBuildConfig({
+  clean: true,
+  entries: ['src/index'],
+  declaration: true,
+  rollup: {
+    emitCJS: true,
+  },
+});
diff --git a/packages/hooks/package.json b/packages/hooks/package.json
new file mode 100644
index 0000000..e27e9ea
--- /dev/null
+++ b/packages/hooks/package.json
@@ -0,0 +1,38 @@
+{
+  "name": "@vben/hooks",
+  "version": "1.0.0",
+  "homepage": "https://github.com/vbenjs/vue-vben-admin",
+  "bugs": {
+    "url": "https://github.com/vbenjs/vue-vben-admin/issues"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
+    "directory": "packages/hooks"
+  },
+  "license": "MIT",
+  "sideEffects": false,
+  "exports": {
+    ".": {
+      "default": "./src/index.ts"
+    }
+  },
+  "main": "./src/index.ts",
+  "module": "./src/index.ts",
+  "files": [
+    "dist"
+  ],
+  "scripts": {
+    "//build": "pnpm unbuild",
+    "//stub": "pnpm unbuild --stub",
+    "clean": "pnpm rimraf .turbo node_modules dist",
+    "lint": "pnpm eslint ."
+  },
+  "dependencies": {
+    "@vueuse/core": "^9.13.0",
+    "vue": "^3.2.47"
+  },
+  "devDependencies": {
+    "@vben/types": "workspace:*"
+  }
+}
diff --git a/packages/hooks/src/index.ts b/packages/hooks/src/index.ts
new file mode 100644
index 0000000..71fb0c5
--- /dev/null
+++ b/packages/hooks/src/index.ts
@@ -0,0 +1,6 @@
+export * from './onMountedOrActivated';
+export * from './useAttrs';
+export * from './useRefs';
+export * from './useScrollTo';
+export * from './useWindowSizeFn';
+export { useTimeoutFn } from '@vueuse/core';
diff --git a/packages/hooks/src/onMountedOrActivated.ts b/packages/hooks/src/onMountedOrActivated.ts
new file mode 100644
index 0000000..53a3c5e
--- /dev/null
+++ b/packages/hooks/src/onMountedOrActivated.ts
@@ -0,0 +1,25 @@
+import { type AnyFunction } from '@vben/types';
+import { nextTick, onActivated, onMounted } from 'vue';
+
+/**
+ * 鍦� OnMounted 鎴栬�� OnActivated 鏃惰Е鍙�
+ * @param hook 浠讳綍鍑芥暟锛堝寘鎷紓姝ュ嚱鏁帮級
+ */
+function onMountedOrActivated(hook: AnyFunction) {
+  let mounted: boolean;
+
+  onMounted(() => {
+    hook();
+    nextTick(() => {
+      mounted = true;
+    });
+  });
+
+  onActivated(() => {
+    if (mounted) {
+      hook();
+    }
+  });
+}
+
+export { onMountedOrActivated };
diff --git a/packages/hooks/src/useAttrs.ts b/packages/hooks/src/useAttrs.ts
new file mode 100644
index 0000000..df2118d
--- /dev/null
+++ b/packages/hooks/src/useAttrs.ts
@@ -0,0 +1,43 @@
+import { type Recordable } from '@vben/types';
+import { getCurrentInstance, reactive, shallowRef, watchEffect } from 'vue';
+
+interface UseAttrsOptions {
+  excludeListeners?: boolean;
+  excludeKeys?: string[];
+  excludeDefaultKeys?: boolean;
+}
+
+const DEFAULT_EXCLUDE_KEYS = ['class', 'style'];
+const LISTENER_PREFIX = /^on[A-Z]/;
+
+function entries<T>(obj: Recordable<T>): [string, T][] {
+  return Object.keys(obj).map((key: string) => [key, obj[key]]);
+}
+
+function useAttrs(options: UseAttrsOptions = {}): Recordable<any> {
+  const instance = getCurrentInstance();
+  if (!instance) return {};
+
+  const { excludeListeners = false, excludeKeys = [], excludeDefaultKeys = true } = options;
+  const attrs = shallowRef({});
+  const allExcludeKeys = excludeKeys.concat(excludeDefaultKeys ? DEFAULT_EXCLUDE_KEYS : []);
+
+  // Since attrs are not reactive, make it reactive instead of doing in `onUpdated` hook for better performance
+  instance.attrs = reactive(instance.attrs);
+
+  watchEffect(() => {
+    const res = entries(instance.attrs).reduce((acm, [key, val]) => {
+      if (!allExcludeKeys.includes(key) && !(excludeListeners && LISTENER_PREFIX.test(key))) {
+        acm[key] = val;
+      }
+
+      return acm;
+    }, {} as Recordable<any>);
+
+    attrs.value = res;
+  });
+
+  return attrs;
+}
+
+export { useAttrs, type UseAttrsOptions };
diff --git a/packages/hooks/src/useRefs.ts b/packages/hooks/src/useRefs.ts
new file mode 100644
index 0000000..97f1b4b
--- /dev/null
+++ b/packages/hooks/src/useRefs.ts
@@ -0,0 +1,24 @@
+import type { Ref } from 'vue';
+import { onBeforeUpdate, shallowRef } from 'vue';
+
+function useRefs(): {
+  refs: Ref<HTMLElement[]>;
+  setRefs: (index: number) => (el: HTMLElement) => void;
+} {
+  const refs = shallowRef([]) as Ref<HTMLElement[]>;
+
+  onBeforeUpdate(() => {
+    refs.value = [];
+  });
+
+  const setRefs = (index: number) => (el: HTMLElement) => {
+    refs.value[index] = el;
+  };
+
+  return {
+    refs,
+    setRefs,
+  };
+}
+
+export { useRefs };
diff --git a/packages/hooks/src/useScrollTo.ts b/packages/hooks/src/useScrollTo.ts
new file mode 100644
index 0000000..f6a95f4
--- /dev/null
+++ b/packages/hooks/src/useScrollTo.ts
@@ -0,0 +1,60 @@
+import { shallowRef, unref } from 'vue';
+
+interface UseScrollToOptions {
+  el: any;
+  to: number;
+  duration?: number;
+  callback?: () => any;
+}
+
+function easeInOutQuad(t: number, b: number, c: number, d: number) {
+  t /= d / 2;
+  if (t < 1) {
+    return (c / 2) * t * t + b;
+  }
+  t--;
+  return (-c / 2) * (t * (t - 2) - 1) + b;
+}
+
+function move(el: HTMLElement, amount: number) {
+  el.scrollTop = amount;
+}
+
+const position = (el: HTMLElement) => {
+  return el.scrollTop;
+};
+function useScrollTo({ el, to, duration = 500, callback }: UseScrollToOptions) {
+  const isActiveRef = shallowRef(false);
+  const start = position(el);
+  const change = to - start;
+  const increment = 20;
+  let currentTime = 0;
+
+  const animateScroll = function () {
+    if (!unref(isActiveRef)) {
+      return;
+    }
+    currentTime += increment;
+    const val = easeInOutQuad(currentTime, start, change, duration);
+    move(el, val);
+    if (currentTime < duration && unref(isActiveRef)) {
+      requestAnimationFrame(animateScroll);
+    } else {
+      if (callback && typeof callback === 'function') {
+        callback();
+      }
+    }
+  };
+  const run = () => {
+    isActiveRef.value = true;
+    animateScroll();
+  };
+
+  const stop = () => {
+    isActiveRef.value = false;
+  };
+
+  return { start: run, stop };
+}
+
+export { useScrollTo, type UseScrollToOptions };
diff --git a/packages/hooks/src/useWindowSizeFn.ts b/packages/hooks/src/useWindowSizeFn.ts
new file mode 100644
index 0000000..d8e7710
--- /dev/null
+++ b/packages/hooks/src/useWindowSizeFn.ts
@@ -0,0 +1,40 @@
+import { type AnyFunction } from '@vben/types';
+import { tryOnMounted, tryOnUnmounted, useDebounceFn } from '@vueuse/core';
+
+interface UseWindowSizeOptions {
+  wait?: number;
+  once?: boolean;
+  immediate?: boolean;
+  listenerOptions?: AddEventListenerOptions | boolean;
+}
+
+function useWindowSizeFn(fn: AnyFunction, options: UseWindowSizeOptions = {}) {
+  const { wait = 150, immediate } = options;
+  let handler = () => {
+    fn();
+  };
+  const handleSize = useDebounceFn(handler, wait);
+  handler = handleSize;
+
+  const start = () => {
+    if (immediate) {
+      handler();
+    }
+    window.addEventListener('resize', handler);
+  };
+
+  const stop = () => {
+    window.removeEventListener('resize', handler);
+  };
+
+  tryOnMounted(() => {
+    start();
+  });
+
+  tryOnUnmounted(() => {
+    stop();
+  });
+  return { start, stop };
+}
+
+export { useWindowSizeFn, type UseWindowSizeOptions };
diff --git a/packages/hooks/tsconfig.json b/packages/hooks/tsconfig.json
new file mode 100644
index 0000000..8508d50
--- /dev/null
+++ b/packages/hooks/tsconfig.json
@@ -0,0 +1,5 @@
+{
+  "$schema": "https://json.schemastore.org/tsconfig",
+  "extends": "@vben/ts-config/vue-app.json",
+  "include": ["src"]
+}
diff --git a/packages/types/.eslintrc.js b/packages/types/.eslintrc.js
new file mode 100644
index 0000000..cd27a19
--- /dev/null
+++ b/packages/types/.eslintrc.js
@@ -0,0 +1,4 @@
+module.exports = {
+  root: true,
+  extends: ['@vben/eslint-config/strict'],
+};
diff --git a/packages/types/build.config.ts b/packages/types/build.config.ts
new file mode 100644
index 0000000..20c8b54
--- /dev/null
+++ b/packages/types/build.config.ts
@@ -0,0 +1,10 @@
+import { defineBuildConfig } from 'unbuild';
+
+export default defineBuildConfig({
+  clean: true,
+  entries: ['src/index'],
+  declaration: true,
+  rollup: {
+    emitCJS: true,
+  },
+});
diff --git a/packages/types/package.json b/packages/types/package.json
new file mode 100644
index 0000000..e2d9023
--- /dev/null
+++ b/packages/types/package.json
@@ -0,0 +1,31 @@
+{
+  "name": "@vben/types",
+  "version": "1.0.0",
+  "homepage": "https://github.com/vbenjs/vue-vben-admin",
+  "bugs": {
+    "url": "https://github.com/vbenjs/vue-vben-admin/issues"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/vbenjs/vue-vben-admin.git",
+    "directory": "packages/types"
+  },
+  "license": "MIT",
+  "sideEffects": false,
+  "exports": {
+    ".": {
+      "default": "./src/index.ts"
+    }
+  },
+  "main": "./src/index.ts",
+  "module": "./src/index.ts",
+  "files": [
+    "dist"
+  ],
+  "scripts": {
+    "//build": "pnpm unbuild",
+    "//stub": "pnpm unbuild --stub",
+    "clean": "pnpm rimraf .turbo node_modules dist",
+    "lint": "pnpm eslint ."
+  }
+}
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
new file mode 100644
index 0000000..04bca77
--- /dev/null
+++ b/packages/types/src/index.ts
@@ -0,0 +1 @@
+export * from './utils';
diff --git a/packages/types/src/utils.ts b/packages/types/src/utils.ts
new file mode 100644
index 0000000..80435fc
--- /dev/null
+++ b/packages/types/src/utils.ts
@@ -0,0 +1,58 @@
+/**
+ * 浠绘剰绫诲瀷鐨勫紓姝ュ嚱鏁�
+ */
+type AnyPromiseFunction = (...arg: any[]) => PromiseLike<any>;
+
+/**
+ * 浠绘剰绫诲瀷鐨勬櫘閫氬嚱鏁�
+ */
+type AnyNormalFunction = (...arg: any[]) => any;
+
+/**
+ * 浠绘剰绫诲瀷鐨勫嚱鏁�
+ */
+type AnyFunction = AnyNormalFunction | AnyPromiseFunction;
+
+/**
+ *  T | null 鍖呰
+ */
+type Nullable<T> = T | null;
+
+/**
+ * T | Not null 鍖呰
+ */
+type NonNullable<T> = T extends null | undefined ? never : T;
+
+/**
+ * 瀛楃涓茬被鍨嬪璞�
+ */
+type Recordable<T> = Record<string, T>;
+
+/**
+ * 瀛楃涓茬被鍨嬪璞★紙鍙锛�
+ */
+interface ReadonlyRecordable<T = any> {
+  readonly [key: string]: T;
+}
+
+/**
+ * setTimeout 杩斿洖鍊肩被鍨�
+ */
+type TimeoutHandle = ReturnType<typeof setTimeout>;
+
+/**
+ * setInterval 杩斿洖鍊肩被鍨�
+ */
+type IntervalHandle = ReturnType<typeof setInterval>;
+
+export {
+  type AnyFunction,
+  type AnyNormalFunction,
+  type AnyPromiseFunction,
+  type IntervalHandle,
+  type NonNullable,
+  type Nullable,
+  type ReadonlyRecordable,
+  type Recordable,
+  type TimeoutHandle,
+};
diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json
new file mode 100644
index 0000000..8508d50
--- /dev/null
+++ b/packages/types/tsconfig.json
@@ -0,0 +1,5 @@
+{
+  "$schema": "https://json.schemastore.org/tsconfig",
+  "extends": "@vben/ts-config/vue-app.json",
+  "include": ["src"]
+}

--
Gitblit v1.9.3