@ -0,0 +1,19 @@ |
|||||
|
root = true |
||||
|
|
||||
|
[*] |
||||
|
charset=utf-8 |
||||
|
end_of_line=LF |
||||
|
insert_final_newline=true |
||||
|
indent_style=space |
||||
|
indent_size=2 |
||||
|
max_line_length = 100 |
||||
|
|
||||
|
[*.{yml,yaml,json}] |
||||
|
indent_style = space |
||||
|
indent_size = 2 |
||||
|
|
||||
|
[*.md] |
||||
|
trim_trailing_whitespace = false |
||||
|
|
||||
|
[Makefile] |
||||
|
indent_style = tab |
@ -0,0 +1,11 @@ |
|||||
|
# port |
||||
|
VITE_PORT = 8081 |
||||
|
|
||||
|
# spa-title |
||||
|
VITE_GLOB_APP_TITLE = DcuiPlus |
||||
|
|
||||
|
# spa shortname |
||||
|
VITE_GLOB_APP_SHORT_NAME = DcuiPlus |
||||
|
|
||||
|
# 生产环境 开启mock |
||||
|
VITE_GLOB_PROD_MOCK = false |
@ -0,0 +1,31 @@ |
|||||
|
# 只在开发模式中被载入 |
||||
|
VITE_PORT = 8081 |
||||
|
|
||||
|
# 网站根目录 |
||||
|
VITE_PUBLIC_PATH = / |
||||
|
|
||||
|
# 是否开启mock |
||||
|
VITE_USE_MOCK = false |
||||
|
|
||||
|
# 网站前缀 |
||||
|
VITE_BASE_URL = / |
||||
|
|
||||
|
# 是否删除console |
||||
|
VITE_DROP_CONSOLE = false |
||||
|
|
||||
|
# 跨域代理,可以配置多个,请注意不要换行 |
||||
|
#VITE_PROXY = [["/appApi","http://localhost:8001"],["/upload","http://localhost:8001/upload"]] |
||||
|
#VITE_PROXY=[["/api","http://10.10.10.56:9000"]] |
||||
|
|
||||
|
# API 接口地址 |
||||
|
VITE_GLOB_API_URL ="http://10.10.10.56:9000" |
||||
|
#VITE_GLOB_API_URL ="http://172.1.2.29:9000" |
||||
|
|
||||
|
# 图片上传地址 |
||||
|
VITE_GLOB_UPLOAD_URL= |
||||
|
|
||||
|
# 图片前缀地址 |
||||
|
VITE_GLOB_IMG_URL= |
||||
|
|
||||
|
# 接口前缀 |
||||
|
VITE_GLOB_API_URL_PREFIX = |
@ -0,0 +1,31 @@ |
|||||
|
# 是否开启mock |
||||
|
VITE_USE_MOCK = false |
||||
|
|
||||
|
# 网站根目录 |
||||
|
VITE_PUBLIC_PATH = / |
||||
|
|
||||
|
# 网站前缀 |
||||
|
VITE_BASE_URL = / |
||||
|
|
||||
|
# 是否删除console |
||||
|
VITE_DROP_CONSOLE = true |
||||
|
|
||||
|
# API |
||||
|
VITE_GLOB_API_URL ="http://10.10.10.56:9000" |
||||
|
|
||||
|
# 图片上传地址 |
||||
|
VITE_GLOB_UPLOAD_URL= |
||||
|
|
||||
|
# 图片前缀地址 |
||||
|
VITE_GLOB_IMG_URL= |
||||
|
|
||||
|
# 接口前缀 |
||||
|
VITE_GLOB_API_URL_PREFIX = |
||||
|
|
||||
|
# 是否启用gzip压缩或brotli压缩 |
||||
|
# 可选: gzip | brotli | none |
||||
|
# 如果你需要多种形式,你可以用','来分隔 |
||||
|
VITE_BUILD_COMPRESS = 'none' |
||||
|
|
||||
|
# 使用压缩时是否删除原始文件,默认为false |
||||
|
VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false |
@ -0,0 +1,16 @@ |
|||||
|
*.sh |
||||
|
node_modules |
||||
|
*.md |
||||
|
*.woff |
||||
|
*.ttf |
||||
|
.vscode |
||||
|
.idea |
||||
|
dist |
||||
|
/public |
||||
|
/docs |
||||
|
.husky |
||||
|
.local |
||||
|
/bin |
||||
|
Dockerfile |
||||
|
components.d.ts |
||||
|
components.d.ts |
@ -0,0 +1,71 @@ |
|||||
|
// @ts-check
|
||||
|
const { defineConfig } = require('eslint-define-config'); |
||||
|
module.exports = defineConfig({ |
||||
|
root: true, |
||||
|
env: { |
||||
|
browser: true, |
||||
|
node: true, |
||||
|
es6: true, |
||||
|
}, |
||||
|
parser: 'vue-eslint-parser', |
||||
|
parserOptions: { |
||||
|
parser: '@typescript-eslint/parser', |
||||
|
ecmaVersion: 2020, |
||||
|
sourceType: 'module', |
||||
|
jsxPragma: 'React', |
||||
|
ecmaFeatures: { |
||||
|
jsx: true, |
||||
|
}, |
||||
|
}, |
||||
|
extends: [ |
||||
|
'plugin:vue/vue3-recommended', |
||||
|
'plugin:@typescript-eslint/recommended', |
||||
|
'prettier', |
||||
|
'plugin:prettier/recommended', |
||||
|
], |
||||
|
rules: { |
||||
|
'vue/script-setup-uses-vars': 'error', |
||||
|
'vue/multi-word-component-names': 'off', |
||||
|
'@typescript-eslint/ban-ts-ignore': 'off', |
||||
|
'@typescript-eslint/explicit-function-return-type': 'off', |
||||
|
'@typescript-eslint/no-explicit-any': 'off', |
||||
|
'@typescript-eslint/no-var-requires': 'off', |
||||
|
'@typescript-eslint/no-empty-function': 'off', |
||||
|
'vue/custom-event-name-casing': 'off', |
||||
|
'no-use-before-define': 'off', |
||||
|
'@typescript-eslint/no-use-before-define': 'off', |
||||
|
'@typescript-eslint/ban-ts-comment': 'off', |
||||
|
'@typescript-eslint/ban-types': 'off', |
||||
|
'@typescript-eslint/no-non-null-assertion': 'off', |
||||
|
'@typescript-eslint/explicit-module-boundary-types': 'off', |
||||
|
'@typescript-eslint/no-unused-vars': ['error', { varsIgnorePattern: '.*', args: 'none' }], |
||||
|
'no-unused-vars': [ |
||||
|
'error', |
||||
|
// we are only using this rule to check for unused arguments since TS
|
||||
|
// catches unused variables but not args.
|
||||
|
{ varsIgnorePattern: '.*', args: 'none' }, |
||||
|
], |
||||
|
'space-before-function-paren': 'off', |
||||
|
|
||||
|
'vue/attributes-order': 'off', |
||||
|
'vue/one-component-per-file': 'off', |
||||
|
'vue/html-closing-bracket-newline': 'off', |
||||
|
'vue/max-attributes-per-line': 'off', |
||||
|
'vue/multiline-html-element-content-newline': 'off', |
||||
|
'vue/singleline-html-element-content-newline': 'off', |
||||
|
'vue/attribute-hyphenation': 'off', |
||||
|
'vue/require-default-prop': 'off', |
||||
|
'vue/html-self-closing': [ |
||||
|
'error', |
||||
|
{ |
||||
|
html: { |
||||
|
void: 'always', |
||||
|
normal: 'never', |
||||
|
component: 'always', |
||||
|
}, |
||||
|
svg: 'always', |
||||
|
math: 'always', |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
}); |
@ -0,0 +1,27 @@ |
|||||
|
.DS_Store |
||||
|
node_modules |
||||
|
/screenshots |
||||
|
/dist |
||||
|
dist.zip |
||||
|
dist_electron |
||||
|
|
||||
|
# local env files |
||||
|
.env.local |
||||
|
.env.*.local |
||||
|
|
||||
|
# Log files |
||||
|
npm-debug.log* |
||||
|
yarn-debug.log* |
||||
|
yarn-error.log* |
||||
|
pnpm-debug.log* |
||||
|
|
||||
|
# Editor directories and files |
||||
|
.idea |
||||
|
.vscode |
||||
|
*.suo |
||||
|
*.ntvs* |
||||
|
*.njsproj |
||||
|
*.sln |
||||
|
*.sw? |
||||
|
/components.d.ts |
||||
|
/components.d.ts |
@ -0,0 +1,9 @@ |
|||||
|
/dist/* |
||||
|
.local |
||||
|
.output.js |
||||
|
/node_modules/** |
||||
|
|
||||
|
**/*.svg |
||||
|
**/*.sh |
||||
|
|
||||
|
/public/* |
@ -0,0 +1,3 @@ |
|||||
|
/dist/* |
||||
|
/public/* |
||||
|
public/* |
@ -1,37 +1,16 @@ |
|||||
# dc-ui-plus |
# dc-ui-plus |
||||
|
|
||||
#### 介绍 |
> 联美运营驾驶舱管理系统 |
||||
naive ui 实现 |
|
||||
|
|
||||
#### 软件架构 |
## Build Setup |
||||
软件架构说明 |
|
||||
|
|
||||
|
``` bash |
||||
|
# install dependencies |
||||
|
npm install |
||||
|
|
||||
#### 安装教程 |
# serve with hot reload at localhost:8081 |
||||
|
npm run dev |
||||
|
|
||||
1. xxxx |
# build for production with minification |
||||
2. xxxx |
npm run build |
||||
3. xxxx |
``` |
||||
|
|
||||
#### 使用说明 |
|
||||
|
|
||||
1. xxxx |
|
||||
2. xxxx |
|
||||
3. xxxx |
|
||||
|
|
||||
#### 参与贡献 |
|
||||
|
|
||||
1. Fork 本仓库 |
|
||||
2. 新建 Feat_xxx 分支 |
|
||||
3. 提交代码 |
|
||||
4. 新建 Pull Request |
|
||||
|
|
||||
|
|
||||
#### 特技 |
|
||||
|
|
||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md |
|
||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) |
|
||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 |
|
||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 |
|
||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) |
|
||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) |
|
@ -0,0 +1,806 @@ |
|||||
|
/* eslint-disable */ |
||||
|
/* prettier-ignore */ |
||||
|
// @ts-nocheck
|
||||
|
// noinspection JSUnusedGlobalSymbols
|
||||
|
// Generated by unplugin-auto-import
|
||||
|
export {} |
||||
|
declare global { |
||||
|
const EffectScope: typeof import('vue')['EffectScope'] |
||||
|
const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] |
||||
|
const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] |
||||
|
const computed: typeof import('vue')['computed'] |
||||
|
const computedAsync: typeof import('@vueuse/core')['computedAsync'] |
||||
|
const computedEager: typeof import('@vueuse/core')['computedEager'] |
||||
|
const computedInject: typeof import('@vueuse/core')['computedInject'] |
||||
|
const computedWithControl: typeof import('@vueuse/core')['computedWithControl'] |
||||
|
const controlledComputed: typeof import('@vueuse/core')['controlledComputed'] |
||||
|
const controlledRef: typeof import('@vueuse/core')['controlledRef'] |
||||
|
const createApp: typeof import('vue')['createApp'] |
||||
|
const createEventHook: typeof import('@vueuse/core')['createEventHook'] |
||||
|
const createGlobalState: typeof import('@vueuse/core')['createGlobalState'] |
||||
|
const createInjectionState: typeof import('@vueuse/core')['createInjectionState'] |
||||
|
const createReactiveFn: typeof import('@vueuse/core')['createReactiveFn'] |
||||
|
const createSharedComposable: typeof import('@vueuse/core')['createSharedComposable'] |
||||
|
const createUnrefFn: typeof import('@vueuse/core')['createUnrefFn'] |
||||
|
const customRef: typeof import('vue')['customRef'] |
||||
|
const debouncedRef: typeof import('@vueuse/core')['debouncedRef'] |
||||
|
const debouncedWatch: typeof import('@vueuse/core')['debouncedWatch'] |
||||
|
const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] |
||||
|
const defineComponent: typeof import('vue')['defineComponent'] |
||||
|
const eagerComputed: typeof import('@vueuse/core')['eagerComputed'] |
||||
|
const effectScope: typeof import('vue')['effectScope'] |
||||
|
const extendRef: typeof import('@vueuse/core')['extendRef'] |
||||
|
const getCurrentInstance: typeof import('vue')['getCurrentInstance'] |
||||
|
const getCurrentScope: typeof import('vue')['getCurrentScope'] |
||||
|
const h: typeof import('vue')['h'] |
||||
|
const ignorableWatch: typeof import('@vueuse/core')['ignorableWatch'] |
||||
|
const inject: typeof import('vue')['inject'] |
||||
|
const isDefined: typeof import('@vueuse/core')['isDefined'] |
||||
|
const isProxy: typeof import('vue')['isProxy'] |
||||
|
const isReactive: typeof import('vue')['isReactive'] |
||||
|
const isReadonly: typeof import('vue')['isReadonly'] |
||||
|
const isRef: typeof import('vue')['isRef'] |
||||
|
const makeDestructurable: typeof import('@vueuse/core')['makeDestructurable'] |
||||
|
const markRaw: typeof import('vue')['markRaw'] |
||||
|
const nextTick: typeof import('vue')['nextTick'] |
||||
|
const onActivated: typeof import('vue')['onActivated'] |
||||
|
const onBeforeMount: typeof import('vue')['onBeforeMount'] |
||||
|
const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] |
||||
|
const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] |
||||
|
const onClickOutside: typeof import('@vueuse/core')['onClickOutside'] |
||||
|
const onDeactivated: typeof import('vue')['onDeactivated'] |
||||
|
const onErrorCaptured: typeof import('vue')['onErrorCaptured'] |
||||
|
const onKeyStroke: typeof import('@vueuse/core')['onKeyStroke'] |
||||
|
const onLongPress: typeof import('@vueuse/core')['onLongPress'] |
||||
|
const onMounted: typeof import('vue')['onMounted'] |
||||
|
const onRenderTracked: typeof import('vue')['onRenderTracked'] |
||||
|
const onRenderTriggered: typeof import('vue')['onRenderTriggered'] |
||||
|
const onScopeDispose: typeof import('vue')['onScopeDispose'] |
||||
|
const onServerPrefetch: typeof import('vue')['onServerPrefetch'] |
||||
|
const onStartTyping: typeof import('@vueuse/core')['onStartTyping'] |
||||
|
const onUnmounted: typeof import('vue')['onUnmounted'] |
||||
|
const onUpdated: typeof import('vue')['onUpdated'] |
||||
|
const pausableWatch: typeof import('@vueuse/core')['pausableWatch'] |
||||
|
const provide: typeof import('vue')['provide'] |
||||
|
const reactify: typeof import('@vueuse/core')['reactify'] |
||||
|
const reactifyObject: typeof import('@vueuse/core')['reactifyObject'] |
||||
|
const reactive: typeof import('vue')['reactive'] |
||||
|
const reactiveComputed: typeof import('@vueuse/core')['reactiveComputed'] |
||||
|
const reactiveOmit: typeof import('@vueuse/core')['reactiveOmit'] |
||||
|
const reactivePick: typeof import('@vueuse/core')['reactivePick'] |
||||
|
const readonly: typeof import('vue')['readonly'] |
||||
|
const ref: typeof import('vue')['ref'] |
||||
|
const refAutoReset: typeof import('@vueuse/core')['refAutoReset'] |
||||
|
const refDebounced: typeof import('@vueuse/core')['refDebounced'] |
||||
|
const refDefault: typeof import('@vueuse/core')['refDefault'] |
||||
|
const refThrottled: typeof import('@vueuse/core')['refThrottled'] |
||||
|
const refWithControl: typeof import('@vueuse/core')['refWithControl'] |
||||
|
const resolveComponent: typeof import('vue')['resolveComponent'] |
||||
|
const resolveRef: typeof import('@vueuse/core')['resolveRef'] |
||||
|
const resolveUnref: typeof import('@vueuse/core')['resolveUnref'] |
||||
|
const shallowReactive: typeof import('vue')['shallowReactive'] |
||||
|
const shallowReadonly: typeof import('vue')['shallowReadonly'] |
||||
|
const shallowRef: typeof import('vue')['shallowRef'] |
||||
|
const syncRef: typeof import('@vueuse/core')['syncRef'] |
||||
|
const syncRefs: typeof import('@vueuse/core')['syncRefs'] |
||||
|
const templateRef: typeof import('@vueuse/core')['templateRef'] |
||||
|
const throttledRef: typeof import('@vueuse/core')['throttledRef'] |
||||
|
const throttledWatch: typeof import('@vueuse/core')['throttledWatch'] |
||||
|
const toRaw: typeof import('vue')['toRaw'] |
||||
|
const toReactive: typeof import('@vueuse/core')['toReactive'] |
||||
|
const toRef: typeof import('vue')['toRef'] |
||||
|
const toRefs: typeof import('vue')['toRefs'] |
||||
|
const toValue: typeof import('vue')['toValue'] |
||||
|
const triggerRef: typeof import('vue')['triggerRef'] |
||||
|
const tryOnBeforeMount: typeof import('@vueuse/core')['tryOnBeforeMount'] |
||||
|
const tryOnBeforeUnmount: typeof import('@vueuse/core')['tryOnBeforeUnmount'] |
||||
|
const tryOnMounted: typeof import('@vueuse/core')['tryOnMounted'] |
||||
|
const tryOnScopeDispose: typeof import('@vueuse/core')['tryOnScopeDispose'] |
||||
|
const tryOnUnmounted: typeof import('@vueuse/core')['tryOnUnmounted'] |
||||
|
const unref: typeof import('vue')['unref'] |
||||
|
const unrefElement: typeof import('@vueuse/core')['unrefElement'] |
||||
|
const until: typeof import('@vueuse/core')['until'] |
||||
|
const useActiveElement: typeof import('@vueuse/core')['useActiveElement'] |
||||
|
const useArrayEvery: typeof import('@vueuse/core')['useArrayEvery'] |
||||
|
const useArrayFilter: typeof import('@vueuse/core')['useArrayFilter'] |
||||
|
const useArrayFind: typeof import('@vueuse/core')['useArrayFind'] |
||||
|
const useArrayFindIndex: typeof import('@vueuse/core')['useArrayFindIndex'] |
||||
|
const useArrayJoin: typeof import('@vueuse/core')['useArrayJoin'] |
||||
|
const useArrayMap: typeof import('@vueuse/core')['useArrayMap'] |
||||
|
const useArrayReduce: typeof import('@vueuse/core')['useArrayReduce'] |
||||
|
const useArraySome: typeof import('@vueuse/core')['useArraySome'] |
||||
|
const useAsyncQueue: typeof import('@vueuse/core')['useAsyncQueue'] |
||||
|
const useAsyncState: typeof import('@vueuse/core')['useAsyncState'] |
||||
|
const useAttrs: typeof import('vue')['useAttrs'] |
||||
|
const useBase64: typeof import('@vueuse/core')['useBase64'] |
||||
|
const useBattery: typeof import('@vueuse/core')['useBattery'] |
||||
|
const useBluetooth: typeof import('@vueuse/core')['useBluetooth'] |
||||
|
const useBreakpoints: typeof import('@vueuse/core')['useBreakpoints'] |
||||
|
const useBroadcastChannel: typeof import('@vueuse/core')['useBroadcastChannel'] |
||||
|
const useBrowserLocation: typeof import('@vueuse/core')['useBrowserLocation'] |
||||
|
const useCached: typeof import('@vueuse/core')['useCached'] |
||||
|
const useClipboard: typeof import('@vueuse/core')['useClipboard'] |
||||
|
const useCloned: typeof import('@vueuse/core')['useCloned'] |
||||
|
const useColorMode: typeof import('@vueuse/core')['useColorMode'] |
||||
|
const useConfirmDialog: typeof import('@vueuse/core')['useConfirmDialog'] |
||||
|
const useCounter: typeof import('@vueuse/core')['useCounter'] |
||||
|
const useCssModule: typeof import('vue')['useCssModule'] |
||||
|
const useCssVar: typeof import('@vueuse/core')['useCssVar'] |
||||
|
const useCssVars: typeof import('vue')['useCssVars'] |
||||
|
const useCurrentElement: typeof import('@vueuse/core')['useCurrentElement'] |
||||
|
const useCycleList: typeof import('@vueuse/core')['useCycleList'] |
||||
|
const useDark: typeof import('@vueuse/core')['useDark'] |
||||
|
const useDateFormat: typeof import('@vueuse/core')['useDateFormat'] |
||||
|
const useDebounce: typeof import('@vueuse/core')['useDebounce'] |
||||
|
const useDebounceFn: typeof import('@vueuse/core')['useDebounceFn'] |
||||
|
const useDebouncedRefHistory: typeof import('@vueuse/core')['useDebouncedRefHistory'] |
||||
|
const useDeviceMotion: typeof import('@vueuse/core')['useDeviceMotion'] |
||||
|
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation'] |
||||
|
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio'] |
||||
|
const useDevicesList: typeof import('@vueuse/core')['useDevicesList'] |
||||
|
const useDialog: typeof import('naive-ui')['useDialog'] |
||||
|
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia'] |
||||
|
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility'] |
||||
|
const useDraggable: typeof import('@vueuse/core')['useDraggable'] |
||||
|
const useDropZone: typeof import('@vueuse/core')['useDropZone'] |
||||
|
const useElementBounding: typeof import('@vueuse/core')['useElementBounding'] |
||||
|
const useElementByPoint: typeof import('@vueuse/core')['useElementByPoint'] |
||||
|
const useElementHover: typeof import('@vueuse/core')['useElementHover'] |
||||
|
const useElementSize: typeof import('@vueuse/core')['useElementSize'] |
||||
|
const useElementVisibility: typeof import('@vueuse/core')['useElementVisibility'] |
||||
|
const useEventBus: typeof import('@vueuse/core')['useEventBus'] |
||||
|
const useEventListener: typeof import('@vueuse/core')['useEventListener'] |
||||
|
const useEventSource: typeof import('@vueuse/core')['useEventSource'] |
||||
|
const useEyeDropper: typeof import('@vueuse/core')['useEyeDropper'] |
||||
|
const useFavicon: typeof import('@vueuse/core')['useFavicon'] |
||||
|
const useFetch: typeof import('@vueuse/core')['useFetch'] |
||||
|
const useFileDialog: typeof import('@vueuse/core')['useFileDialog'] |
||||
|
const useFileSystemAccess: typeof import('@vueuse/core')['useFileSystemAccess'] |
||||
|
const useFocus: typeof import('@vueuse/core')['useFocus'] |
||||
|
const useFocusWithin: typeof import('@vueuse/core')['useFocusWithin'] |
||||
|
const useFps: typeof import('@vueuse/core')['useFps'] |
||||
|
const useFullscreen: typeof import('@vueuse/core')['useFullscreen'] |
||||
|
const useGamepad: typeof import('@vueuse/core')['useGamepad'] |
||||
|
const useGeolocation: typeof import('@vueuse/core')['useGeolocation'] |
||||
|
const useIdle: typeof import('@vueuse/core')['useIdle'] |
||||
|
const useImage: typeof import('@vueuse/core')['useImage'] |
||||
|
const useInfiniteScroll: typeof import('@vueuse/core')['useInfiniteScroll'] |
||||
|
const useIntersectionObserver: typeof import('@vueuse/core')['useIntersectionObserver'] |
||||
|
const useInterval: typeof import('@vueuse/core')['useInterval'] |
||||
|
const useIntervalFn: typeof import('@vueuse/core')['useIntervalFn'] |
||||
|
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier'] |
||||
|
const useLastChanged: typeof import('@vueuse/core')['useLastChanged'] |
||||
|
const useLoadingBar: typeof import('naive-ui')['useLoadingBar'] |
||||
|
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage'] |
||||
|
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys'] |
||||
|
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory'] |
||||
|
const useMediaControls: typeof import('@vueuse/core')['useMediaControls'] |
||||
|
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery'] |
||||
|
const useMemoize: typeof import('@vueuse/core')['useMemoize'] |
||||
|
const useMemory: typeof import('@vueuse/core')['useMemory'] |
||||
|
const useMessage: typeof import('naive-ui')['useMessage'] |
||||
|
const useMounted: typeof import('@vueuse/core')['useMounted'] |
||||
|
const useMouse: typeof import('@vueuse/core')['useMouse'] |
||||
|
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement'] |
||||
|
const useMousePressed: typeof import('@vueuse/core')['useMousePressed'] |
||||
|
const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver'] |
||||
|
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage'] |
||||
|
const useNetwork: typeof import('@vueuse/core')['useNetwork'] |
||||
|
const useNotification: typeof import('naive-ui')['useNotification'] |
||||
|
const useNow: typeof import('@vueuse/core')['useNow'] |
||||
|
const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl'] |
||||
|
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination'] |
||||
|
const useOnline: typeof import('@vueuse/core')['useOnline'] |
||||
|
const usePageLeave: typeof import('@vueuse/core')['usePageLeave'] |
||||
|
const useParallax: typeof import('@vueuse/core')['useParallax'] |
||||
|
const usePermission: typeof import('@vueuse/core')['usePermission'] |
||||
|
const usePointer: typeof import('@vueuse/core')['usePointer'] |
||||
|
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe'] |
||||
|
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme'] |
||||
|
const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast'] |
||||
|
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark'] |
||||
|
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages'] |
||||
|
const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion'] |
||||
|
const useRafFn: typeof import('@vueuse/core')['useRafFn'] |
||||
|
const useRefHistory: typeof import('@vueuse/core')['useRefHistory'] |
||||
|
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver'] |
||||
|
const useScreenOrientation: typeof import('@vueuse/core')['useScreenOrientation'] |
||||
|
const useScreenSafeArea: typeof import('@vueuse/core')['useScreenSafeArea'] |
||||
|
const useScriptTag: typeof import('@vueuse/core')['useScriptTag'] |
||||
|
const useScroll: typeof import('@vueuse/core')['useScroll'] |
||||
|
const useScrollLock: typeof import('@vueuse/core')['useScrollLock'] |
||||
|
const useSessionStorage: typeof import('@vueuse/core')['useSessionStorage'] |
||||
|
const useShare: typeof import('@vueuse/core')['useShare'] |
||||
|
const useSlots: typeof import('vue')['useSlots'] |
||||
|
const useSorted: typeof import('@vueuse/core')['useSorted'] |
||||
|
const useSpeechRecognition: typeof import('@vueuse/core')['useSpeechRecognition'] |
||||
|
const useSpeechSynthesis: typeof import('@vueuse/core')['useSpeechSynthesis'] |
||||
|
const useStepper: typeof import('@vueuse/core')['useStepper'] |
||||
|
const useStorage: typeof import('@vueuse/core')['useStorage'] |
||||
|
const useStorageAsync: typeof import('@vueuse/core')['useStorageAsync'] |
||||
|
const useStyleTag: typeof import('@vueuse/core')['useStyleTag'] |
||||
|
const useSupported: typeof import('@vueuse/core')['useSupported'] |
||||
|
const useSwipe: typeof import('@vueuse/core')['useSwipe'] |
||||
|
const useTemplateRefsList: typeof import('@vueuse/core')['useTemplateRefsList'] |
||||
|
const useTextDirection: typeof import('@vueuse/core')['useTextDirection'] |
||||
|
const useTextSelection: typeof import('@vueuse/core')['useTextSelection'] |
||||
|
const useTextareaAutosize: typeof import('@vueuse/core')['useTextareaAutosize'] |
||||
|
const useThrottle: typeof import('@vueuse/core')['useThrottle'] |
||||
|
const useThrottleFn: typeof import('@vueuse/core')['useThrottleFn'] |
||||
|
const useThrottledRefHistory: typeof import('@vueuse/core')['useThrottledRefHistory'] |
||||
|
const useTimeAgo: typeof import('@vueuse/core')['useTimeAgo'] |
||||
|
const useTimeout: typeof import('@vueuse/core')['useTimeout'] |
||||
|
const useTimeoutFn: typeof import('@vueuse/core')['useTimeoutFn'] |
||||
|
const useTimeoutPoll: typeof import('@vueuse/core')['useTimeoutPoll'] |
||||
|
const useTimestamp: typeof import('@vueuse/core')['useTimestamp'] |
||||
|
const useTitle: typeof import('@vueuse/core')['useTitle'] |
||||
|
const useToNumber: typeof import('@vueuse/core')['useToNumber'] |
||||
|
const useToString: typeof import('@vueuse/core')['useToString'] |
||||
|
const useToggle: typeof import('@vueuse/core')['useToggle'] |
||||
|
const useTransition: typeof import('@vueuse/core')['useTransition'] |
||||
|
const useUrlSearchParams: typeof import('@vueuse/core')['useUrlSearchParams'] |
||||
|
const useUserMedia: typeof import('@vueuse/core')['useUserMedia'] |
||||
|
const useVModel: typeof import('@vueuse/core')['useVModel'] |
||||
|
const useVModels: typeof import('@vueuse/core')['useVModels'] |
||||
|
const useVibrate: typeof import('@vueuse/core')['useVibrate'] |
||||
|
const useVirtualList: typeof import('@vueuse/core')['useVirtualList'] |
||||
|
const useWakeLock: typeof import('@vueuse/core')['useWakeLock'] |
||||
|
const useWebNotification: typeof import('@vueuse/core')['useWebNotification'] |
||||
|
const useWebSocket: typeof import('@vueuse/core')['useWebSocket'] |
||||
|
const useWebWorker: typeof import('@vueuse/core')['useWebWorker'] |
||||
|
const useWebWorkerFn: typeof import('@vueuse/core')['useWebWorkerFn'] |
||||
|
const useWindowFocus: typeof import('@vueuse/core')['useWindowFocus'] |
||||
|
const useWindowScroll: typeof import('@vueuse/core')['useWindowScroll'] |
||||
|
const useWindowSize: typeof import('@vueuse/core')['useWindowSize'] |
||||
|
const watch: typeof import('vue')['watch'] |
||||
|
const watchArray: typeof import('@vueuse/core')['watchArray'] |
||||
|
const watchAtMost: typeof import('@vueuse/core')['watchAtMost'] |
||||
|
const watchDebounced: typeof import('@vueuse/core')['watchDebounced'] |
||||
|
const watchEffect: typeof import('vue')['watchEffect'] |
||||
|
const watchIgnorable: typeof import('@vueuse/core')['watchIgnorable'] |
||||
|
const watchOnce: typeof import('@vueuse/core')['watchOnce'] |
||||
|
const watchPausable: typeof import('@vueuse/core')['watchPausable'] |
||||
|
const watchPostEffect: typeof import('vue')['watchPostEffect'] |
||||
|
const watchSyncEffect: typeof import('vue')['watchSyncEffect'] |
||||
|
const watchThrottled: typeof import('@vueuse/core')['watchThrottled'] |
||||
|
const watchTriggerable: typeof import('@vueuse/core')['watchTriggerable'] |
||||
|
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter'] |
||||
|
const whenever: typeof import('@vueuse/core')['whenever'] |
||||
|
} |
||||
|
// for type re-export
|
||||
|
declare global { |
||||
|
// @ts-ignore
|
||||
|
export type { Component, ComponentPublicInstance, ComputedRef, InjectionKey, PropType, Ref, VNode } from 'vue' |
||||
|
} |
||||
|
// for vue template auto import
|
||||
|
import { UnwrapRef } from 'vue' |
||||
|
declare module 'vue' { |
||||
|
interface ComponentCustomProperties { |
||||
|
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']> |
||||
|
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']> |
||||
|
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']> |
||||
|
readonly computed: UnwrapRef<typeof import('vue')['computed']> |
||||
|
readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']> |
||||
|
readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']> |
||||
|
readonly computedInject: UnwrapRef<typeof import('@vueuse/core')['computedInject']> |
||||
|
readonly computedWithControl: UnwrapRef<typeof import('@vueuse/core')['computedWithControl']> |
||||
|
readonly controlledComputed: UnwrapRef<typeof import('@vueuse/core')['controlledComputed']> |
||||
|
readonly controlledRef: UnwrapRef<typeof import('@vueuse/core')['controlledRef']> |
||||
|
readonly createApp: UnwrapRef<typeof import('vue')['createApp']> |
||||
|
readonly createEventHook: UnwrapRef<typeof import('@vueuse/core')['createEventHook']> |
||||
|
readonly createGlobalState: UnwrapRef<typeof import('@vueuse/core')['createGlobalState']> |
||||
|
readonly createInjectionState: UnwrapRef<typeof import('@vueuse/core')['createInjectionState']> |
||||
|
readonly createReactiveFn: UnwrapRef<typeof import('@vueuse/core')['createReactiveFn']> |
||||
|
readonly createSharedComposable: UnwrapRef<typeof import('@vueuse/core')['createSharedComposable']> |
||||
|
readonly createUnrefFn: UnwrapRef<typeof import('@vueuse/core')['createUnrefFn']> |
||||
|
readonly customRef: UnwrapRef<typeof import('vue')['customRef']> |
||||
|
readonly debouncedRef: UnwrapRef<typeof import('@vueuse/core')['debouncedRef']> |
||||
|
readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']> |
||||
|
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']> |
||||
|
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']> |
||||
|
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']> |
||||
|
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']> |
||||
|
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']> |
||||
|
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']> |
||||
|
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']> |
||||
|
readonly h: UnwrapRef<typeof import('vue')['h']> |
||||
|
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']> |
||||
|
readonly inject: UnwrapRef<typeof import('vue')['inject']> |
||||
|
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']> |
||||
|
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']> |
||||
|
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']> |
||||
|
readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']> |
||||
|
readonly isRef: UnwrapRef<typeof import('vue')['isRef']> |
||||
|
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']> |
||||
|
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']> |
||||
|
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']> |
||||
|
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']> |
||||
|
readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']> |
||||
|
readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']> |
||||
|
readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']> |
||||
|
readonly onClickOutside: UnwrapRef<typeof import('@vueuse/core')['onClickOutside']> |
||||
|
readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']> |
||||
|
readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']> |
||||
|
readonly onKeyStroke: UnwrapRef<typeof import('@vueuse/core')['onKeyStroke']> |
||||
|
readonly onLongPress: UnwrapRef<typeof import('@vueuse/core')['onLongPress']> |
||||
|
readonly onMounted: UnwrapRef<typeof import('vue')['onMounted']> |
||||
|
readonly onRenderTracked: UnwrapRef<typeof import('vue')['onRenderTracked']> |
||||
|
readonly onRenderTriggered: UnwrapRef<typeof import('vue')['onRenderTriggered']> |
||||
|
readonly onScopeDispose: UnwrapRef<typeof import('vue')['onScopeDispose']> |
||||
|
readonly onServerPrefetch: UnwrapRef<typeof import('vue')['onServerPrefetch']> |
||||
|
readonly onStartTyping: UnwrapRef<typeof import('@vueuse/core')['onStartTyping']> |
||||
|
readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']> |
||||
|
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']> |
||||
|
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']> |
||||
|
readonly provide: UnwrapRef<typeof import('vue')['provide']> |
||||
|
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']> |
||||
|
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']> |
||||
|
readonly reactive: UnwrapRef<typeof import('vue')['reactive']> |
||||
|
readonly reactiveComputed: UnwrapRef<typeof import('@vueuse/core')['reactiveComputed']> |
||||
|
readonly reactiveOmit: UnwrapRef<typeof import('@vueuse/core')['reactiveOmit']> |
||||
|
readonly reactivePick: UnwrapRef<typeof import('@vueuse/core')['reactivePick']> |
||||
|
readonly readonly: UnwrapRef<typeof import('vue')['readonly']> |
||||
|
readonly ref: UnwrapRef<typeof import('vue')['ref']> |
||||
|
readonly refAutoReset: UnwrapRef<typeof import('@vueuse/core')['refAutoReset']> |
||||
|
readonly refDebounced: UnwrapRef<typeof import('@vueuse/core')['refDebounced']> |
||||
|
readonly refDefault: UnwrapRef<typeof import('@vueuse/core')['refDefault']> |
||||
|
readonly refThrottled: UnwrapRef<typeof import('@vueuse/core')['refThrottled']> |
||||
|
readonly refWithControl: UnwrapRef<typeof import('@vueuse/core')['refWithControl']> |
||||
|
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']> |
||||
|
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']> |
||||
|
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']> |
||||
|
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']> |
||||
|
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']> |
||||
|
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']> |
||||
|
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']> |
||||
|
readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']> |
||||
|
readonly templateRef: UnwrapRef<typeof import('@vueuse/core')['templateRef']> |
||||
|
readonly throttledRef: UnwrapRef<typeof import('@vueuse/core')['throttledRef']> |
||||
|
readonly throttledWatch: UnwrapRef<typeof import('@vueuse/core')['throttledWatch']> |
||||
|
readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']> |
||||
|
readonly toReactive: UnwrapRef<typeof import('@vueuse/core')['toReactive']> |
||||
|
readonly toRef: UnwrapRef<typeof import('vue')['toRef']> |
||||
|
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']> |
||||
|
readonly toValue: UnwrapRef<typeof import('vue')['toValue']> |
||||
|
readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']> |
||||
|
readonly tryOnBeforeMount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeMount']> |
||||
|
readonly tryOnBeforeUnmount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeUnmount']> |
||||
|
readonly tryOnMounted: UnwrapRef<typeof import('@vueuse/core')['tryOnMounted']> |
||||
|
readonly tryOnScopeDispose: UnwrapRef<typeof import('@vueuse/core')['tryOnScopeDispose']> |
||||
|
readonly tryOnUnmounted: UnwrapRef<typeof import('@vueuse/core')['tryOnUnmounted']> |
||||
|
readonly unref: UnwrapRef<typeof import('vue')['unref']> |
||||
|
readonly unrefElement: UnwrapRef<typeof import('@vueuse/core')['unrefElement']> |
||||
|
readonly until: UnwrapRef<typeof import('@vueuse/core')['until']> |
||||
|
readonly useActiveElement: UnwrapRef<typeof import('@vueuse/core')['useActiveElement']> |
||||
|
readonly useArrayEvery: UnwrapRef<typeof import('@vueuse/core')['useArrayEvery']> |
||||
|
readonly useArrayFilter: UnwrapRef<typeof import('@vueuse/core')['useArrayFilter']> |
||||
|
readonly useArrayFind: UnwrapRef<typeof import('@vueuse/core')['useArrayFind']> |
||||
|
readonly useArrayFindIndex: UnwrapRef<typeof import('@vueuse/core')['useArrayFindIndex']> |
||||
|
readonly useArrayJoin: UnwrapRef<typeof import('@vueuse/core')['useArrayJoin']> |
||||
|
readonly useArrayMap: UnwrapRef<typeof import('@vueuse/core')['useArrayMap']> |
||||
|
readonly useArrayReduce: UnwrapRef<typeof import('@vueuse/core')['useArrayReduce']> |
||||
|
readonly useArraySome: UnwrapRef<typeof import('@vueuse/core')['useArraySome']> |
||||
|
readonly useAsyncQueue: UnwrapRef<typeof import('@vueuse/core')['useAsyncQueue']> |
||||
|
readonly useAsyncState: UnwrapRef<typeof import('@vueuse/core')['useAsyncState']> |
||||
|
readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']> |
||||
|
readonly useBase64: UnwrapRef<typeof import('@vueuse/core')['useBase64']> |
||||
|
readonly useBattery: UnwrapRef<typeof import('@vueuse/core')['useBattery']> |
||||
|
readonly useBluetooth: UnwrapRef<typeof import('@vueuse/core')['useBluetooth']> |
||||
|
readonly useBreakpoints: UnwrapRef<typeof import('@vueuse/core')['useBreakpoints']> |
||||
|
readonly useBroadcastChannel: UnwrapRef<typeof import('@vueuse/core')['useBroadcastChannel']> |
||||
|
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']> |
||||
|
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']> |
||||
|
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']> |
||||
|
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']> |
||||
|
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']> |
||||
|
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']> |
||||
|
readonly useCounter: UnwrapRef<typeof import('@vueuse/core')['useCounter']> |
||||
|
readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']> |
||||
|
readonly useCssVar: UnwrapRef<typeof import('@vueuse/core')['useCssVar']> |
||||
|
readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']> |
||||
|
readonly useCurrentElement: UnwrapRef<typeof import('@vueuse/core')['useCurrentElement']> |
||||
|
readonly useCycleList: UnwrapRef<typeof import('@vueuse/core')['useCycleList']> |
||||
|
readonly useDark: UnwrapRef<typeof import('@vueuse/core')['useDark']> |
||||
|
readonly useDateFormat: UnwrapRef<typeof import('@vueuse/core')['useDateFormat']> |
||||
|
readonly useDebounce: UnwrapRef<typeof import('@vueuse/core')['useDebounce']> |
||||
|
readonly useDebounceFn: UnwrapRef<typeof import('@vueuse/core')['useDebounceFn']> |
||||
|
readonly useDebouncedRefHistory: UnwrapRef<typeof import('@vueuse/core')['useDebouncedRefHistory']> |
||||
|
readonly useDeviceMotion: UnwrapRef<typeof import('@vueuse/core')['useDeviceMotion']> |
||||
|
readonly useDeviceOrientation: UnwrapRef<typeof import('@vueuse/core')['useDeviceOrientation']> |
||||
|
readonly useDevicePixelRatio: UnwrapRef<typeof import('@vueuse/core')['useDevicePixelRatio']> |
||||
|
readonly useDevicesList: UnwrapRef<typeof import('@vueuse/core')['useDevicesList']> |
||||
|
readonly useDialog: UnwrapRef<typeof import('naive-ui')['useDialog']> |
||||
|
readonly useDisplayMedia: UnwrapRef<typeof import('@vueuse/core')['useDisplayMedia']> |
||||
|
readonly useDocumentVisibility: UnwrapRef<typeof import('@vueuse/core')['useDocumentVisibility']> |
||||
|
readonly useDraggable: UnwrapRef<typeof import('@vueuse/core')['useDraggable']> |
||||
|
readonly useDropZone: UnwrapRef<typeof import('@vueuse/core')['useDropZone']> |
||||
|
readonly useElementBounding: UnwrapRef<typeof import('@vueuse/core')['useElementBounding']> |
||||
|
readonly useElementByPoint: UnwrapRef<typeof import('@vueuse/core')['useElementByPoint']> |
||||
|
readonly useElementHover: UnwrapRef<typeof import('@vueuse/core')['useElementHover']> |
||||
|
readonly useElementSize: UnwrapRef<typeof import('@vueuse/core')['useElementSize']> |
||||
|
readonly useElementVisibility: UnwrapRef<typeof import('@vueuse/core')['useElementVisibility']> |
||||
|
readonly useEventBus: UnwrapRef<typeof import('@vueuse/core')['useEventBus']> |
||||
|
readonly useEventListener: UnwrapRef<typeof import('@vueuse/core')['useEventListener']> |
||||
|
readonly useEventSource: UnwrapRef<typeof import('@vueuse/core')['useEventSource']> |
||||
|
readonly useEyeDropper: UnwrapRef<typeof import('@vueuse/core')['useEyeDropper']> |
||||
|
readonly useFavicon: UnwrapRef<typeof import('@vueuse/core')['useFavicon']> |
||||
|
readonly useFetch: UnwrapRef<typeof import('@vueuse/core')['useFetch']> |
||||
|
readonly useFileDialog: UnwrapRef<typeof import('@vueuse/core')['useFileDialog']> |
||||
|
readonly useFileSystemAccess: UnwrapRef<typeof import('@vueuse/core')['useFileSystemAccess']> |
||||
|
readonly useFocus: UnwrapRef<typeof import('@vueuse/core')['useFocus']> |
||||
|
readonly useFocusWithin: UnwrapRef<typeof import('@vueuse/core')['useFocusWithin']> |
||||
|
readonly useFps: UnwrapRef<typeof import('@vueuse/core')['useFps']> |
||||
|
readonly useFullscreen: UnwrapRef<typeof import('@vueuse/core')['useFullscreen']> |
||||
|
readonly useGamepad: UnwrapRef<typeof import('@vueuse/core')['useGamepad']> |
||||
|
readonly useGeolocation: UnwrapRef<typeof import('@vueuse/core')['useGeolocation']> |
||||
|
readonly useIdle: UnwrapRef<typeof import('@vueuse/core')['useIdle']> |
||||
|
readonly useImage: UnwrapRef<typeof import('@vueuse/core')['useImage']> |
||||
|
readonly useInfiniteScroll: UnwrapRef<typeof import('@vueuse/core')['useInfiniteScroll']> |
||||
|
readonly useIntersectionObserver: UnwrapRef<typeof import('@vueuse/core')['useIntersectionObserver']> |
||||
|
readonly useInterval: UnwrapRef<typeof import('@vueuse/core')['useInterval']> |
||||
|
readonly useIntervalFn: UnwrapRef<typeof import('@vueuse/core')['useIntervalFn']> |
||||
|
readonly useKeyModifier: UnwrapRef<typeof import('@vueuse/core')['useKeyModifier']> |
||||
|
readonly useLastChanged: UnwrapRef<typeof import('@vueuse/core')['useLastChanged']> |
||||
|
readonly useLoadingBar: UnwrapRef<typeof import('naive-ui')['useLoadingBar']> |
||||
|
readonly useLocalStorage: UnwrapRef<typeof import('@vueuse/core')['useLocalStorage']> |
||||
|
readonly useMagicKeys: UnwrapRef<typeof import('@vueuse/core')['useMagicKeys']> |
||||
|
readonly useManualRefHistory: UnwrapRef<typeof import('@vueuse/core')['useManualRefHistory']> |
||||
|
readonly useMediaControls: UnwrapRef<typeof import('@vueuse/core')['useMediaControls']> |
||||
|
readonly useMediaQuery: UnwrapRef<typeof import('@vueuse/core')['useMediaQuery']> |
||||
|
readonly useMemoize: UnwrapRef<typeof import('@vueuse/core')['useMemoize']> |
||||
|
readonly useMemory: UnwrapRef<typeof import('@vueuse/core')['useMemory']> |
||||
|
readonly useMessage: UnwrapRef<typeof import('naive-ui')['useMessage']> |
||||
|
readonly useMounted: UnwrapRef<typeof import('@vueuse/core')['useMounted']> |
||||
|
readonly useMouse: UnwrapRef<typeof import('@vueuse/core')['useMouse']> |
||||
|
readonly useMouseInElement: UnwrapRef<typeof import('@vueuse/core')['useMouseInElement']> |
||||
|
readonly useMousePressed: UnwrapRef<typeof import('@vueuse/core')['useMousePressed']> |
||||
|
readonly useMutationObserver: UnwrapRef<typeof import('@vueuse/core')['useMutationObserver']> |
||||
|
readonly useNavigatorLanguage: UnwrapRef<typeof import('@vueuse/core')['useNavigatorLanguage']> |
||||
|
readonly useNetwork: UnwrapRef<typeof import('@vueuse/core')['useNetwork']> |
||||
|
readonly useNotification: UnwrapRef<typeof import('naive-ui')['useNotification']> |
||||
|
readonly useNow: UnwrapRef<typeof import('@vueuse/core')['useNow']> |
||||
|
readonly useObjectUrl: UnwrapRef<typeof import('@vueuse/core')['useObjectUrl']> |
||||
|
readonly useOffsetPagination: UnwrapRef<typeof import('@vueuse/core')['useOffsetPagination']> |
||||
|
readonly useOnline: UnwrapRef<typeof import('@vueuse/core')['useOnline']> |
||||
|
readonly usePageLeave: UnwrapRef<typeof import('@vueuse/core')['usePageLeave']> |
||||
|
readonly useParallax: UnwrapRef<typeof import('@vueuse/core')['useParallax']> |
||||
|
readonly usePermission: UnwrapRef<typeof import('@vueuse/core')['usePermission']> |
||||
|
readonly usePointer: UnwrapRef<typeof import('@vueuse/core')['usePointer']> |
||||
|
readonly usePointerSwipe: UnwrapRef<typeof import('@vueuse/core')['usePointerSwipe']> |
||||
|
readonly usePreferredColorScheme: UnwrapRef<typeof import('@vueuse/core')['usePreferredColorScheme']> |
||||
|
readonly usePreferredContrast: UnwrapRef<typeof import('@vueuse/core')['usePreferredContrast']> |
||||
|
readonly usePreferredDark: UnwrapRef<typeof import('@vueuse/core')['usePreferredDark']> |
||||
|
readonly usePreferredLanguages: UnwrapRef<typeof import('@vueuse/core')['usePreferredLanguages']> |
||||
|
readonly usePreferredReducedMotion: UnwrapRef<typeof import('@vueuse/core')['usePreferredReducedMotion']> |
||||
|
readonly useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']> |
||||
|
readonly useRefHistory: UnwrapRef<typeof import('@vueuse/core')['useRefHistory']> |
||||
|
readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']> |
||||
|
readonly useScreenOrientation: UnwrapRef<typeof import('@vueuse/core')['useScreenOrientation']> |
||||
|
readonly useScreenSafeArea: UnwrapRef<typeof import('@vueuse/core')['useScreenSafeArea']> |
||||
|
readonly useScriptTag: UnwrapRef<typeof import('@vueuse/core')['useScriptTag']> |
||||
|
readonly useScroll: UnwrapRef<typeof import('@vueuse/core')['useScroll']> |
||||
|
readonly useScrollLock: UnwrapRef<typeof import('@vueuse/core')['useScrollLock']> |
||||
|
readonly useSessionStorage: UnwrapRef<typeof import('@vueuse/core')['useSessionStorage']> |
||||
|
readonly useShare: UnwrapRef<typeof import('@vueuse/core')['useShare']> |
||||
|
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']> |
||||
|
readonly useSorted: UnwrapRef<typeof import('@vueuse/core')['useSorted']> |
||||
|
readonly useSpeechRecognition: UnwrapRef<typeof import('@vueuse/core')['useSpeechRecognition']> |
||||
|
readonly useSpeechSynthesis: UnwrapRef<typeof import('@vueuse/core')['useSpeechSynthesis']> |
||||
|
readonly useStepper: UnwrapRef<typeof import('@vueuse/core')['useStepper']> |
||||
|
readonly useStorage: UnwrapRef<typeof import('@vueuse/core')['useStorage']> |
||||
|
readonly useStorageAsync: UnwrapRef<typeof import('@vueuse/core')['useStorageAsync']> |
||||
|
readonly useStyleTag: UnwrapRef<typeof import('@vueuse/core')['useStyleTag']> |
||||
|
readonly useSupported: UnwrapRef<typeof import('@vueuse/core')['useSupported']> |
||||
|
readonly useSwipe: UnwrapRef<typeof import('@vueuse/core')['useSwipe']> |
||||
|
readonly useTemplateRefsList: UnwrapRef<typeof import('@vueuse/core')['useTemplateRefsList']> |
||||
|
readonly useTextDirection: UnwrapRef<typeof import('@vueuse/core')['useTextDirection']> |
||||
|
readonly useTextSelection: UnwrapRef<typeof import('@vueuse/core')['useTextSelection']> |
||||
|
readonly useTextareaAutosize: UnwrapRef<typeof import('@vueuse/core')['useTextareaAutosize']> |
||||
|
readonly useThrottle: UnwrapRef<typeof import('@vueuse/core')['useThrottle']> |
||||
|
readonly useThrottleFn: UnwrapRef<typeof import('@vueuse/core')['useThrottleFn']> |
||||
|
readonly useThrottledRefHistory: UnwrapRef<typeof import('@vueuse/core')['useThrottledRefHistory']> |
||||
|
readonly useTimeAgo: UnwrapRef<typeof import('@vueuse/core')['useTimeAgo']> |
||||
|
readonly useTimeout: UnwrapRef<typeof import('@vueuse/core')['useTimeout']> |
||||
|
readonly useTimeoutFn: UnwrapRef<typeof import('@vueuse/core')['useTimeoutFn']> |
||||
|
readonly useTimeoutPoll: UnwrapRef<typeof import('@vueuse/core')['useTimeoutPoll']> |
||||
|
readonly useTimestamp: UnwrapRef<typeof import('@vueuse/core')['useTimestamp']> |
||||
|
readonly useTitle: UnwrapRef<typeof import('@vueuse/core')['useTitle']> |
||||
|
readonly useToNumber: UnwrapRef<typeof import('@vueuse/core')['useToNumber']> |
||||
|
readonly useToString: UnwrapRef<typeof import('@vueuse/core')['useToString']> |
||||
|
readonly useToggle: UnwrapRef<typeof import('@vueuse/core')['useToggle']> |
||||
|
readonly useTransition: UnwrapRef<typeof import('@vueuse/core')['useTransition']> |
||||
|
readonly useUrlSearchParams: UnwrapRef<typeof import('@vueuse/core')['useUrlSearchParams']> |
||||
|
readonly useUserMedia: UnwrapRef<typeof import('@vueuse/core')['useUserMedia']> |
||||
|
readonly useVModel: UnwrapRef<typeof import('@vueuse/core')['useVModel']> |
||||
|
readonly useVModels: UnwrapRef<typeof import('@vueuse/core')['useVModels']> |
||||
|
readonly useVibrate: UnwrapRef<typeof import('@vueuse/core')['useVibrate']> |
||||
|
readonly useVirtualList: UnwrapRef<typeof import('@vueuse/core')['useVirtualList']> |
||||
|
readonly useWakeLock: UnwrapRef<typeof import('@vueuse/core')['useWakeLock']> |
||||
|
readonly useWebNotification: UnwrapRef<typeof import('@vueuse/core')['useWebNotification']> |
||||
|
readonly useWebSocket: UnwrapRef<typeof import('@vueuse/core')['useWebSocket']> |
||||
|
readonly useWebWorker: UnwrapRef<typeof import('@vueuse/core')['useWebWorker']> |
||||
|
readonly useWebWorkerFn: UnwrapRef<typeof import('@vueuse/core')['useWebWorkerFn']> |
||||
|
readonly useWindowFocus: UnwrapRef<typeof import('@vueuse/core')['useWindowFocus']> |
||||
|
readonly useWindowScroll: UnwrapRef<typeof import('@vueuse/core')['useWindowScroll']> |
||||
|
readonly useWindowSize: UnwrapRef<typeof import('@vueuse/core')['useWindowSize']> |
||||
|
readonly watch: UnwrapRef<typeof import('vue')['watch']> |
||||
|
readonly watchArray: UnwrapRef<typeof import('@vueuse/core')['watchArray']> |
||||
|
readonly watchAtMost: UnwrapRef<typeof import('@vueuse/core')['watchAtMost']> |
||||
|
readonly watchDebounced: UnwrapRef<typeof import('@vueuse/core')['watchDebounced']> |
||||
|
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']> |
||||
|
readonly watchIgnorable: UnwrapRef<typeof import('@vueuse/core')['watchIgnorable']> |
||||
|
readonly watchOnce: UnwrapRef<typeof import('@vueuse/core')['watchOnce']> |
||||
|
readonly watchPausable: UnwrapRef<typeof import('@vueuse/core')['watchPausable']> |
||||
|
readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']> |
||||
|
readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']> |
||||
|
readonly watchThrottled: UnwrapRef<typeof import('@vueuse/core')['watchThrottled']> |
||||
|
readonly watchTriggerable: UnwrapRef<typeof import('@vueuse/core')['watchTriggerable']> |
||||
|
readonly watchWithFilter: UnwrapRef<typeof import('@vueuse/core')['watchWithFilter']> |
||||
|
readonly whenever: UnwrapRef<typeof import('@vueuse/core')['whenever']> |
||||
|
} |
||||
|
} |
||||
|
declare module '@vue/runtime-core' { |
||||
|
interface ComponentCustomProperties { |
||||
|
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']> |
||||
|
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']> |
||||
|
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']> |
||||
|
readonly computed: UnwrapRef<typeof import('vue')['computed']> |
||||
|
readonly computedAsync: UnwrapRef<typeof import('@vueuse/core')['computedAsync']> |
||||
|
readonly computedEager: UnwrapRef<typeof import('@vueuse/core')['computedEager']> |
||||
|
readonly computedInject: UnwrapRef<typeof import('@vueuse/core')['computedInject']> |
||||
|
readonly computedWithControl: UnwrapRef<typeof import('@vueuse/core')['computedWithControl']> |
||||
|
readonly controlledComputed: UnwrapRef<typeof import('@vueuse/core')['controlledComputed']> |
||||
|
readonly controlledRef: UnwrapRef<typeof import('@vueuse/core')['controlledRef']> |
||||
|
readonly createApp: UnwrapRef<typeof import('vue')['createApp']> |
||||
|
readonly createEventHook: UnwrapRef<typeof import('@vueuse/core')['createEventHook']> |
||||
|
readonly createGlobalState: UnwrapRef<typeof import('@vueuse/core')['createGlobalState']> |
||||
|
readonly createInjectionState: UnwrapRef<typeof import('@vueuse/core')['createInjectionState']> |
||||
|
readonly createReactiveFn: UnwrapRef<typeof import('@vueuse/core')['createReactiveFn']> |
||||
|
readonly createSharedComposable: UnwrapRef<typeof import('@vueuse/core')['createSharedComposable']> |
||||
|
readonly createUnrefFn: UnwrapRef<typeof import('@vueuse/core')['createUnrefFn']> |
||||
|
readonly customRef: UnwrapRef<typeof import('vue')['customRef']> |
||||
|
readonly debouncedRef: UnwrapRef<typeof import('@vueuse/core')['debouncedRef']> |
||||
|
readonly debouncedWatch: UnwrapRef<typeof import('@vueuse/core')['debouncedWatch']> |
||||
|
readonly defineAsyncComponent: UnwrapRef<typeof import('vue')['defineAsyncComponent']> |
||||
|
readonly defineComponent: UnwrapRef<typeof import('vue')['defineComponent']> |
||||
|
readonly eagerComputed: UnwrapRef<typeof import('@vueuse/core')['eagerComputed']> |
||||
|
readonly effectScope: UnwrapRef<typeof import('vue')['effectScope']> |
||||
|
readonly extendRef: UnwrapRef<typeof import('@vueuse/core')['extendRef']> |
||||
|
readonly getCurrentInstance: UnwrapRef<typeof import('vue')['getCurrentInstance']> |
||||
|
readonly getCurrentScope: UnwrapRef<typeof import('vue')['getCurrentScope']> |
||||
|
readonly h: UnwrapRef<typeof import('vue')['h']> |
||||
|
readonly ignorableWatch: UnwrapRef<typeof import('@vueuse/core')['ignorableWatch']> |
||||
|
readonly inject: UnwrapRef<typeof import('vue')['inject']> |
||||
|
readonly isDefined: UnwrapRef<typeof import('@vueuse/core')['isDefined']> |
||||
|
readonly isProxy: UnwrapRef<typeof import('vue')['isProxy']> |
||||
|
readonly isReactive: UnwrapRef<typeof import('vue')['isReactive']> |
||||
|
readonly isReadonly: UnwrapRef<typeof import('vue')['isReadonly']> |
||||
|
readonly isRef: UnwrapRef<typeof import('vue')['isRef']> |
||||
|
readonly makeDestructurable: UnwrapRef<typeof import('@vueuse/core')['makeDestructurable']> |
||||
|
readonly markRaw: UnwrapRef<typeof import('vue')['markRaw']> |
||||
|
readonly nextTick: UnwrapRef<typeof import('vue')['nextTick']> |
||||
|
readonly onActivated: UnwrapRef<typeof import('vue')['onActivated']> |
||||
|
readonly onBeforeMount: UnwrapRef<typeof import('vue')['onBeforeMount']> |
||||
|
readonly onBeforeUnmount: UnwrapRef<typeof import('vue')['onBeforeUnmount']> |
||||
|
readonly onBeforeUpdate: UnwrapRef<typeof import('vue')['onBeforeUpdate']> |
||||
|
readonly onClickOutside: UnwrapRef<typeof import('@vueuse/core')['onClickOutside']> |
||||
|
readonly onDeactivated: UnwrapRef<typeof import('vue')['onDeactivated']> |
||||
|
readonly onErrorCaptured: UnwrapRef<typeof import('vue')['onErrorCaptured']> |
||||
|
readonly onKeyStroke: UnwrapRef<typeof import('@vueuse/core')['onKeyStroke']> |
||||
|
readonly onLongPress: UnwrapRef<typeof import('@vueuse/core')['onLongPress']> |
||||
|
readonly onMounted: UnwrapRef<typeof import('vue')['onMounted']> |
||||
|
readonly onRenderTracked: UnwrapRef<typeof import('vue')['onRenderTracked']> |
||||
|
readonly onRenderTriggered: UnwrapRef<typeof import('vue')['onRenderTriggered']> |
||||
|
readonly onScopeDispose: UnwrapRef<typeof import('vue')['onScopeDispose']> |
||||
|
readonly onServerPrefetch: UnwrapRef<typeof import('vue')['onServerPrefetch']> |
||||
|
readonly onStartTyping: UnwrapRef<typeof import('@vueuse/core')['onStartTyping']> |
||||
|
readonly onUnmounted: UnwrapRef<typeof import('vue')['onUnmounted']> |
||||
|
readonly onUpdated: UnwrapRef<typeof import('vue')['onUpdated']> |
||||
|
readonly pausableWatch: UnwrapRef<typeof import('@vueuse/core')['pausableWatch']> |
||||
|
readonly provide: UnwrapRef<typeof import('vue')['provide']> |
||||
|
readonly reactify: UnwrapRef<typeof import('@vueuse/core')['reactify']> |
||||
|
readonly reactifyObject: UnwrapRef<typeof import('@vueuse/core')['reactifyObject']> |
||||
|
readonly reactive: UnwrapRef<typeof import('vue')['reactive']> |
||||
|
readonly reactiveComputed: UnwrapRef<typeof import('@vueuse/core')['reactiveComputed']> |
||||
|
readonly reactiveOmit: UnwrapRef<typeof import('@vueuse/core')['reactiveOmit']> |
||||
|
readonly reactivePick: UnwrapRef<typeof import('@vueuse/core')['reactivePick']> |
||||
|
readonly readonly: UnwrapRef<typeof import('vue')['readonly']> |
||||
|
readonly ref: UnwrapRef<typeof import('vue')['ref']> |
||||
|
readonly refAutoReset: UnwrapRef<typeof import('@vueuse/core')['refAutoReset']> |
||||
|
readonly refDebounced: UnwrapRef<typeof import('@vueuse/core')['refDebounced']> |
||||
|
readonly refDefault: UnwrapRef<typeof import('@vueuse/core')['refDefault']> |
||||
|
readonly refThrottled: UnwrapRef<typeof import('@vueuse/core')['refThrottled']> |
||||
|
readonly refWithControl: UnwrapRef<typeof import('@vueuse/core')['refWithControl']> |
||||
|
readonly resolveComponent: UnwrapRef<typeof import('vue')['resolveComponent']> |
||||
|
readonly resolveRef: UnwrapRef<typeof import('@vueuse/core')['resolveRef']> |
||||
|
readonly resolveUnref: UnwrapRef<typeof import('@vueuse/core')['resolveUnref']> |
||||
|
readonly shallowReactive: UnwrapRef<typeof import('vue')['shallowReactive']> |
||||
|
readonly shallowReadonly: UnwrapRef<typeof import('vue')['shallowReadonly']> |
||||
|
readonly shallowRef: UnwrapRef<typeof import('vue')['shallowRef']> |
||||
|
readonly syncRef: UnwrapRef<typeof import('@vueuse/core')['syncRef']> |
||||
|
readonly syncRefs: UnwrapRef<typeof import('@vueuse/core')['syncRefs']> |
||||
|
readonly templateRef: UnwrapRef<typeof import('@vueuse/core')['templateRef']> |
||||
|
readonly throttledRef: UnwrapRef<typeof import('@vueuse/core')['throttledRef']> |
||||
|
readonly throttledWatch: UnwrapRef<typeof import('@vueuse/core')['throttledWatch']> |
||||
|
readonly toRaw: UnwrapRef<typeof import('vue')['toRaw']> |
||||
|
readonly toReactive: UnwrapRef<typeof import('@vueuse/core')['toReactive']> |
||||
|
readonly toRef: UnwrapRef<typeof import('vue')['toRef']> |
||||
|
readonly toRefs: UnwrapRef<typeof import('vue')['toRefs']> |
||||
|
readonly toValue: UnwrapRef<typeof import('vue')['toValue']> |
||||
|
readonly triggerRef: UnwrapRef<typeof import('vue')['triggerRef']> |
||||
|
readonly tryOnBeforeMount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeMount']> |
||||
|
readonly tryOnBeforeUnmount: UnwrapRef<typeof import('@vueuse/core')['tryOnBeforeUnmount']> |
||||
|
readonly tryOnMounted: UnwrapRef<typeof import('@vueuse/core')['tryOnMounted']> |
||||
|
readonly tryOnScopeDispose: UnwrapRef<typeof import('@vueuse/core')['tryOnScopeDispose']> |
||||
|
readonly tryOnUnmounted: UnwrapRef<typeof import('@vueuse/core')['tryOnUnmounted']> |
||||
|
readonly unref: UnwrapRef<typeof import('vue')['unref']> |
||||
|
readonly unrefElement: UnwrapRef<typeof import('@vueuse/core')['unrefElement']> |
||||
|
readonly until: UnwrapRef<typeof import('@vueuse/core')['until']> |
||||
|
readonly useActiveElement: UnwrapRef<typeof import('@vueuse/core')['useActiveElement']> |
||||
|
readonly useArrayEvery: UnwrapRef<typeof import('@vueuse/core')['useArrayEvery']> |
||||
|
readonly useArrayFilter: UnwrapRef<typeof import('@vueuse/core')['useArrayFilter']> |
||||
|
readonly useArrayFind: UnwrapRef<typeof import('@vueuse/core')['useArrayFind']> |
||||
|
readonly useArrayFindIndex: UnwrapRef<typeof import('@vueuse/core')['useArrayFindIndex']> |
||||
|
readonly useArrayJoin: UnwrapRef<typeof import('@vueuse/core')['useArrayJoin']> |
||||
|
readonly useArrayMap: UnwrapRef<typeof import('@vueuse/core')['useArrayMap']> |
||||
|
readonly useArrayReduce: UnwrapRef<typeof import('@vueuse/core')['useArrayReduce']> |
||||
|
readonly useArraySome: UnwrapRef<typeof import('@vueuse/core')['useArraySome']> |
||||
|
readonly useAsyncQueue: UnwrapRef<typeof import('@vueuse/core')['useAsyncQueue']> |
||||
|
readonly useAsyncState: UnwrapRef<typeof import('@vueuse/core')['useAsyncState']> |
||||
|
readonly useAttrs: UnwrapRef<typeof import('vue')['useAttrs']> |
||||
|
readonly useBase64: UnwrapRef<typeof import('@vueuse/core')['useBase64']> |
||||
|
readonly useBattery: UnwrapRef<typeof import('@vueuse/core')['useBattery']> |
||||
|
readonly useBluetooth: UnwrapRef<typeof import('@vueuse/core')['useBluetooth']> |
||||
|
readonly useBreakpoints: UnwrapRef<typeof import('@vueuse/core')['useBreakpoints']> |
||||
|
readonly useBroadcastChannel: UnwrapRef<typeof import('@vueuse/core')['useBroadcastChannel']> |
||||
|
readonly useBrowserLocation: UnwrapRef<typeof import('@vueuse/core')['useBrowserLocation']> |
||||
|
readonly useCached: UnwrapRef<typeof import('@vueuse/core')['useCached']> |
||||
|
readonly useClipboard: UnwrapRef<typeof import('@vueuse/core')['useClipboard']> |
||||
|
readonly useCloned: UnwrapRef<typeof import('@vueuse/core')['useCloned']> |
||||
|
readonly useColorMode: UnwrapRef<typeof import('@vueuse/core')['useColorMode']> |
||||
|
readonly useConfirmDialog: UnwrapRef<typeof import('@vueuse/core')['useConfirmDialog']> |
||||
|
readonly useCounter: UnwrapRef<typeof import('@vueuse/core')['useCounter']> |
||||
|
readonly useCssModule: UnwrapRef<typeof import('vue')['useCssModule']> |
||||
|
readonly useCssVar: UnwrapRef<typeof import('@vueuse/core')['useCssVar']> |
||||
|
readonly useCssVars: UnwrapRef<typeof import('vue')['useCssVars']> |
||||
|
readonly useCurrentElement: UnwrapRef<typeof import('@vueuse/core')['useCurrentElement']> |
||||
|
readonly useCycleList: UnwrapRef<typeof import('@vueuse/core')['useCycleList']> |
||||
|
readonly useDark: UnwrapRef<typeof import('@vueuse/core')['useDark']> |
||||
|
readonly useDateFormat: UnwrapRef<typeof import('@vueuse/core')['useDateFormat']> |
||||
|
readonly useDebounce: UnwrapRef<typeof import('@vueuse/core')['useDebounce']> |
||||
|
readonly useDebounceFn: UnwrapRef<typeof import('@vueuse/core')['useDebounceFn']> |
||||
|
readonly useDebouncedRefHistory: UnwrapRef<typeof import('@vueuse/core')['useDebouncedRefHistory']> |
||||
|
readonly useDeviceMotion: UnwrapRef<typeof import('@vueuse/core')['useDeviceMotion']> |
||||
|
readonly useDeviceOrientation: UnwrapRef<typeof import('@vueuse/core')['useDeviceOrientation']> |
||||
|
readonly useDevicePixelRatio: UnwrapRef<typeof import('@vueuse/core')['useDevicePixelRatio']> |
||||
|
readonly useDevicesList: UnwrapRef<typeof import('@vueuse/core')['useDevicesList']> |
||||
|
readonly useDialog: UnwrapRef<typeof import('naive-ui')['useDialog']> |
||||
|
readonly useDisplayMedia: UnwrapRef<typeof import('@vueuse/core')['useDisplayMedia']> |
||||
|
readonly useDocumentVisibility: UnwrapRef<typeof import('@vueuse/core')['useDocumentVisibility']> |
||||
|
readonly useDraggable: UnwrapRef<typeof import('@vueuse/core')['useDraggable']> |
||||
|
readonly useDropZone: UnwrapRef<typeof import('@vueuse/core')['useDropZone']> |
||||
|
readonly useElementBounding: UnwrapRef<typeof import('@vueuse/core')['useElementBounding']> |
||||
|
readonly useElementByPoint: UnwrapRef<typeof import('@vueuse/core')['useElementByPoint']> |
||||
|
readonly useElementHover: UnwrapRef<typeof import('@vueuse/core')['useElementHover']> |
||||
|
readonly useElementSize: UnwrapRef<typeof import('@vueuse/core')['useElementSize']> |
||||
|
readonly useElementVisibility: UnwrapRef<typeof import('@vueuse/core')['useElementVisibility']> |
||||
|
readonly useEventBus: UnwrapRef<typeof import('@vueuse/core')['useEventBus']> |
||||
|
readonly useEventListener: UnwrapRef<typeof import('@vueuse/core')['useEventListener']> |
||||
|
readonly useEventSource: UnwrapRef<typeof import('@vueuse/core')['useEventSource']> |
||||
|
readonly useEyeDropper: UnwrapRef<typeof import('@vueuse/core')['useEyeDropper']> |
||||
|
readonly useFavicon: UnwrapRef<typeof import('@vueuse/core')['useFavicon']> |
||||
|
readonly useFetch: UnwrapRef<typeof import('@vueuse/core')['useFetch']> |
||||
|
readonly useFileDialog: UnwrapRef<typeof import('@vueuse/core')['useFileDialog']> |
||||
|
readonly useFileSystemAccess: UnwrapRef<typeof import('@vueuse/core')['useFileSystemAccess']> |
||||
|
readonly useFocus: UnwrapRef<typeof import('@vueuse/core')['useFocus']> |
||||
|
readonly useFocusWithin: UnwrapRef<typeof import('@vueuse/core')['useFocusWithin']> |
||||
|
readonly useFps: UnwrapRef<typeof import('@vueuse/core')['useFps']> |
||||
|
readonly useFullscreen: UnwrapRef<typeof import('@vueuse/core')['useFullscreen']> |
||||
|
readonly useGamepad: UnwrapRef<typeof import('@vueuse/core')['useGamepad']> |
||||
|
readonly useGeolocation: UnwrapRef<typeof import('@vueuse/core')['useGeolocation']> |
||||
|
readonly useIdle: UnwrapRef<typeof import('@vueuse/core')['useIdle']> |
||||
|
readonly useImage: UnwrapRef<typeof import('@vueuse/core')['useImage']> |
||||
|
readonly useInfiniteScroll: UnwrapRef<typeof import('@vueuse/core')['useInfiniteScroll']> |
||||
|
readonly useIntersectionObserver: UnwrapRef<typeof import('@vueuse/core')['useIntersectionObserver']> |
||||
|
readonly useInterval: UnwrapRef<typeof import('@vueuse/core')['useInterval']> |
||||
|
readonly useIntervalFn: UnwrapRef<typeof import('@vueuse/core')['useIntervalFn']> |
||||
|
readonly useKeyModifier: UnwrapRef<typeof import('@vueuse/core')['useKeyModifier']> |
||||
|
readonly useLastChanged: UnwrapRef<typeof import('@vueuse/core')['useLastChanged']> |
||||
|
readonly useLoadingBar: UnwrapRef<typeof import('naive-ui')['useLoadingBar']> |
||||
|
readonly useLocalStorage: UnwrapRef<typeof import('@vueuse/core')['useLocalStorage']> |
||||
|
readonly useMagicKeys: UnwrapRef<typeof import('@vueuse/core')['useMagicKeys']> |
||||
|
readonly useManualRefHistory: UnwrapRef<typeof import('@vueuse/core')['useManualRefHistory']> |
||||
|
readonly useMediaControls: UnwrapRef<typeof import('@vueuse/core')['useMediaControls']> |
||||
|
readonly useMediaQuery: UnwrapRef<typeof import('@vueuse/core')['useMediaQuery']> |
||||
|
readonly useMemoize: UnwrapRef<typeof import('@vueuse/core')['useMemoize']> |
||||
|
readonly useMemory: UnwrapRef<typeof import('@vueuse/core')['useMemory']> |
||||
|
readonly useMessage: UnwrapRef<typeof import('naive-ui')['useMessage']> |
||||
|
readonly useMounted: UnwrapRef<typeof import('@vueuse/core')['useMounted']> |
||||
|
readonly useMouse: UnwrapRef<typeof import('@vueuse/core')['useMouse']> |
||||
|
readonly useMouseInElement: UnwrapRef<typeof import('@vueuse/core')['useMouseInElement']> |
||||
|
readonly useMousePressed: UnwrapRef<typeof import('@vueuse/core')['useMousePressed']> |
||||
|
readonly useMutationObserver: UnwrapRef<typeof import('@vueuse/core')['useMutationObserver']> |
||||
|
readonly useNavigatorLanguage: UnwrapRef<typeof import('@vueuse/core')['useNavigatorLanguage']> |
||||
|
readonly useNetwork: UnwrapRef<typeof import('@vueuse/core')['useNetwork']> |
||||
|
readonly useNotification: UnwrapRef<typeof import('naive-ui')['useNotification']> |
||||
|
readonly useNow: UnwrapRef<typeof import('@vueuse/core')['useNow']> |
||||
|
readonly useObjectUrl: UnwrapRef<typeof import('@vueuse/core')['useObjectUrl']> |
||||
|
readonly useOffsetPagination: UnwrapRef<typeof import('@vueuse/core')['useOffsetPagination']> |
||||
|
readonly useOnline: UnwrapRef<typeof import('@vueuse/core')['useOnline']> |
||||
|
readonly usePageLeave: UnwrapRef<typeof import('@vueuse/core')['usePageLeave']> |
||||
|
readonly useParallax: UnwrapRef<typeof import('@vueuse/core')['useParallax']> |
||||
|
readonly usePermission: UnwrapRef<typeof import('@vueuse/core')['usePermission']> |
||||
|
readonly usePointer: UnwrapRef<typeof import('@vueuse/core')['usePointer']> |
||||
|
readonly usePointerSwipe: UnwrapRef<typeof import('@vueuse/core')['usePointerSwipe']> |
||||
|
readonly usePreferredColorScheme: UnwrapRef<typeof import('@vueuse/core')['usePreferredColorScheme']> |
||||
|
readonly usePreferredContrast: UnwrapRef<typeof import('@vueuse/core')['usePreferredContrast']> |
||||
|
readonly usePreferredDark: UnwrapRef<typeof import('@vueuse/core')['usePreferredDark']> |
||||
|
readonly usePreferredLanguages: UnwrapRef<typeof import('@vueuse/core')['usePreferredLanguages']> |
||||
|
readonly usePreferredReducedMotion: UnwrapRef<typeof import('@vueuse/core')['usePreferredReducedMotion']> |
||||
|
readonly useRafFn: UnwrapRef<typeof import('@vueuse/core')['useRafFn']> |
||||
|
readonly useRefHistory: UnwrapRef<typeof import('@vueuse/core')['useRefHistory']> |
||||
|
readonly useResizeObserver: UnwrapRef<typeof import('@vueuse/core')['useResizeObserver']> |
||||
|
readonly useScreenOrientation: UnwrapRef<typeof import('@vueuse/core')['useScreenOrientation']> |
||||
|
readonly useScreenSafeArea: UnwrapRef<typeof import('@vueuse/core')['useScreenSafeArea']> |
||||
|
readonly useScriptTag: UnwrapRef<typeof import('@vueuse/core')['useScriptTag']> |
||||
|
readonly useScroll: UnwrapRef<typeof import('@vueuse/core')['useScroll']> |
||||
|
readonly useScrollLock: UnwrapRef<typeof import('@vueuse/core')['useScrollLock']> |
||||
|
readonly useSessionStorage: UnwrapRef<typeof import('@vueuse/core')['useSessionStorage']> |
||||
|
readonly useShare: UnwrapRef<typeof import('@vueuse/core')['useShare']> |
||||
|
readonly useSlots: UnwrapRef<typeof import('vue')['useSlots']> |
||||
|
readonly useSorted: UnwrapRef<typeof import('@vueuse/core')['useSorted']> |
||||
|
readonly useSpeechRecognition: UnwrapRef<typeof import('@vueuse/core')['useSpeechRecognition']> |
||||
|
readonly useSpeechSynthesis: UnwrapRef<typeof import('@vueuse/core')['useSpeechSynthesis']> |
||||
|
readonly useStepper: UnwrapRef<typeof import('@vueuse/core')['useStepper']> |
||||
|
readonly useStorage: UnwrapRef<typeof import('@vueuse/core')['useStorage']> |
||||
|
readonly useStorageAsync: UnwrapRef<typeof import('@vueuse/core')['useStorageAsync']> |
||||
|
readonly useStyleTag: UnwrapRef<typeof import('@vueuse/core')['useStyleTag']> |
||||
|
readonly useSupported: UnwrapRef<typeof import('@vueuse/core')['useSupported']> |
||||
|
readonly useSwipe: UnwrapRef<typeof import('@vueuse/core')['useSwipe']> |
||||
|
readonly useTemplateRefsList: UnwrapRef<typeof import('@vueuse/core')['useTemplateRefsList']> |
||||
|
readonly useTextDirection: UnwrapRef<typeof import('@vueuse/core')['useTextDirection']> |
||||
|
readonly useTextSelection: UnwrapRef<typeof import('@vueuse/core')['useTextSelection']> |
||||
|
readonly useTextareaAutosize: UnwrapRef<typeof import('@vueuse/core')['useTextareaAutosize']> |
||||
|
readonly useThrottle: UnwrapRef<typeof import('@vueuse/core')['useThrottle']> |
||||
|
readonly useThrottleFn: UnwrapRef<typeof import('@vueuse/core')['useThrottleFn']> |
||||
|
readonly useThrottledRefHistory: UnwrapRef<typeof import('@vueuse/core')['useThrottledRefHistory']> |
||||
|
readonly useTimeAgo: UnwrapRef<typeof import('@vueuse/core')['useTimeAgo']> |
||||
|
readonly useTimeout: UnwrapRef<typeof import('@vueuse/core')['useTimeout']> |
||||
|
readonly useTimeoutFn: UnwrapRef<typeof import('@vueuse/core')['useTimeoutFn']> |
||||
|
readonly useTimeoutPoll: UnwrapRef<typeof import('@vueuse/core')['useTimeoutPoll']> |
||||
|
readonly useTimestamp: UnwrapRef<typeof import('@vueuse/core')['useTimestamp']> |
||||
|
readonly useTitle: UnwrapRef<typeof import('@vueuse/core')['useTitle']> |
||||
|
readonly useToNumber: UnwrapRef<typeof import('@vueuse/core')['useToNumber']> |
||||
|
readonly useToString: UnwrapRef<typeof import('@vueuse/core')['useToString']> |
||||
|
readonly useToggle: UnwrapRef<typeof import('@vueuse/core')['useToggle']> |
||||
|
readonly useTransition: UnwrapRef<typeof import('@vueuse/core')['useTransition']> |
||||
|
readonly useUrlSearchParams: UnwrapRef<typeof import('@vueuse/core')['useUrlSearchParams']> |
||||
|
readonly useUserMedia: UnwrapRef<typeof import('@vueuse/core')['useUserMedia']> |
||||
|
readonly useVModel: UnwrapRef<typeof import('@vueuse/core')['useVModel']> |
||||
|
readonly useVModels: UnwrapRef<typeof import('@vueuse/core')['useVModels']> |
||||
|
readonly useVibrate: UnwrapRef<typeof import('@vueuse/core')['useVibrate']> |
||||
|
readonly useVirtualList: UnwrapRef<typeof import('@vueuse/core')['useVirtualList']> |
||||
|
readonly useWakeLock: UnwrapRef<typeof import('@vueuse/core')['useWakeLock']> |
||||
|
readonly useWebNotification: UnwrapRef<typeof import('@vueuse/core')['useWebNotification']> |
||||
|
readonly useWebSocket: UnwrapRef<typeof import('@vueuse/core')['useWebSocket']> |
||||
|
readonly useWebWorker: UnwrapRef<typeof import('@vueuse/core')['useWebWorker']> |
||||
|
readonly useWebWorkerFn: UnwrapRef<typeof import('@vueuse/core')['useWebWorkerFn']> |
||||
|
readonly useWindowFocus: UnwrapRef<typeof import('@vueuse/core')['useWindowFocus']> |
||||
|
readonly useWindowScroll: UnwrapRef<typeof import('@vueuse/core')['useWindowScroll']> |
||||
|
readonly useWindowSize: UnwrapRef<typeof import('@vueuse/core')['useWindowSize']> |
||||
|
readonly watch: UnwrapRef<typeof import('vue')['watch']> |
||||
|
readonly watchArray: UnwrapRef<typeof import('@vueuse/core')['watchArray']> |
||||
|
readonly watchAtMost: UnwrapRef<typeof import('@vueuse/core')['watchAtMost']> |
||||
|
readonly watchDebounced: UnwrapRef<typeof import('@vueuse/core')['watchDebounced']> |
||||
|
readonly watchEffect: UnwrapRef<typeof import('vue')['watchEffect']> |
||||
|
readonly watchIgnorable: UnwrapRef<typeof import('@vueuse/core')['watchIgnorable']> |
||||
|
readonly watchOnce: UnwrapRef<typeof import('@vueuse/core')['watchOnce']> |
||||
|
readonly watchPausable: UnwrapRef<typeof import('@vueuse/core')['watchPausable']> |
||||
|
readonly watchPostEffect: UnwrapRef<typeof import('vue')['watchPostEffect']> |
||||
|
readonly watchSyncEffect: UnwrapRef<typeof import('vue')['watchSyncEffect']> |
||||
|
readonly watchThrottled: UnwrapRef<typeof import('@vueuse/core')['watchThrottled']> |
||||
|
readonly watchTriggerable: UnwrapRef<typeof import('@vueuse/core')['watchTriggerable']> |
||||
|
readonly watchWithFilter: UnwrapRef<typeof import('@vueuse/core')['watchWithFilter']> |
||||
|
readonly whenever: UnwrapRef<typeof import('@vueuse/core')['whenever']> |
||||
|
} |
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
/** |
||||
|
* The name of the configuration file entered in the production environment |
||||
|
*/ |
||||
|
export const GLOB_CONFIG_FILE_NAME = 'app.config.js'; |
||||
|
|
||||
|
export const OUTPUT_DIR = 'dist'; |
@ -0,0 +1,9 @@ |
|||||
|
/** |
||||
|
* Get the configuration file variable name |
||||
|
* @param env |
||||
|
*/ |
||||
|
export const getConfigFileName = (env: Record<string, any>) => { |
||||
|
return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__` |
||||
|
.toUpperCase() |
||||
|
.replace(/\s/g, ''); |
||||
|
}; |
@ -0,0 +1,44 @@ |
|||||
|
/** |
||||
|
* Generate additional configuration files when used for packaging. The file can be configured with some global variables, so that it can be changed directly externally without repackaging |
||||
|
*/ |
||||
|
import { GLOB_CONFIG_FILE_NAME, OUTPUT_DIR } from '../constant'; |
||||
|
import fs, { writeFileSync } from 'fs-extra'; |
||||
|
import chalk from 'chalk'; |
||||
|
|
||||
|
import { getRootPath, getEnvConfig } from '../utils'; |
||||
|
import { getConfigFileName } from '../getConfigFileName'; |
||||
|
|
||||
|
import pkg from '../../package.json'; |
||||
|
|
||||
|
function createConfig( |
||||
|
{ |
||||
|
configName, |
||||
|
config, |
||||
|
configFileName = GLOB_CONFIG_FILE_NAME, |
||||
|
}: { configName: string; config: any; configFileName?: string } = { configName: '', config: {} } |
||||
|
) { |
||||
|
try { |
||||
|
const windowConf = `window.${configName}`; |
||||
|
// Ensure that the variable will not be modified
|
||||
|
const configStr = `${windowConf}=${JSON.stringify(config)};
|
||||
|
Object.freeze(${windowConf}); |
||||
|
Object.defineProperty(window, "${configName}", { |
||||
|
configurable: false, |
||||
|
writable: false, |
||||
|
}); |
||||
|
`.replace(/\s/g, '');
|
||||
|
fs.mkdirp(getRootPath(OUTPUT_DIR)); |
||||
|
writeFileSync(getRootPath(`${OUTPUT_DIR}/${configFileName}`), configStr); |
||||
|
|
||||
|
console.log(chalk.cyan(`✨ [${pkg.name}]`) + ` - configuration file is build successfully:`); |
||||
|
console.log(chalk.gray(OUTPUT_DIR + '/' + chalk.green(configFileName)) + '\n'); |
||||
|
} catch (error) { |
||||
|
console.log(chalk.red('configuration file configuration file failed to package:\n' + error)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export function runBuildConfig() { |
||||
|
const config = getEnvConfig(); |
||||
|
const configFileName = getConfigFileName(config); |
||||
|
createConfig({ config, configName: configFileName }); |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
// #!/usr/bin/env node
|
||||
|
|
||||
|
import { runBuildConfig } from './buildConf'; |
||||
|
import chalk from 'chalk'; |
||||
|
|
||||
|
import pkg from '../../package.json'; |
||||
|
|
||||
|
export const runBuild = async () => { |
||||
|
try { |
||||
|
const argvList = process.argv.splice(2); |
||||
|
|
||||
|
// Generate configuration file
|
||||
|
if (!argvList.includes('disabled-config')) { |
||||
|
await runBuildConfig(); |
||||
|
} |
||||
|
|
||||
|
console.log(`✨ ${chalk.cyan(`[${pkg.name}]`)}` + ' - build successfully!'); |
||||
|
} catch (error) { |
||||
|
console.log(chalk.red('vite build error:\n' + error)); |
||||
|
process.exit(1); |
||||
|
} |
||||
|
}; |
||||
|
runBuild(); |
@ -0,0 +1,71 @@ |
|||||
|
import fs from 'fs'; |
||||
|
import path from 'path'; |
||||
|
import dotenv from 'dotenv'; |
||||
|
|
||||
|
export function isDevFn(mode: string): boolean { |
||||
|
return mode === 'development'; |
||||
|
} |
||||
|
|
||||
|
export function isProdFn(mode: string): boolean { |
||||
|
return mode === 'production'; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Whether to generate package preview |
||||
|
*/ |
||||
|
export function isReportMode(): boolean { |
||||
|
return process.env.REPORT === 'true'; |
||||
|
} |
||||
|
|
||||
|
// Read all environment variable configuration files to process.env
|
||||
|
export function wrapperEnv(envConf: Recordable): ViteEnv { |
||||
|
const ret: any = {}; |
||||
|
|
||||
|
for (const envName of Object.keys(envConf)) { |
||||
|
let realName = envConf[envName].replace(/\\n/g, '\n'); |
||||
|
realName = realName === 'true' ? true : realName === 'false' ? false : realName; |
||||
|
|
||||
|
if (envName === 'VITE_PORT') { |
||||
|
realName = Number(realName); |
||||
|
} |
||||
|
if (envName === 'VITE_PROXY') { |
||||
|
try { |
||||
|
realName = JSON.parse(realName); |
||||
|
} catch (error) {} |
||||
|
} |
||||
|
ret[envName] = realName; |
||||
|
process.env[envName] = realName; |
||||
|
} |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get the environment variables starting with the specified prefix |
||||
|
* @param match prefix |
||||
|
* @param confFiles ext |
||||
|
*/ |
||||
|
export function getEnvConfig(match = 'VITE_GLOB_', confFiles = ['.env', '.env.production']) { |
||||
|
let envConfig = {}; |
||||
|
confFiles.forEach((item) => { |
||||
|
try { |
||||
|
const env = dotenv.parse(fs.readFileSync(path.resolve(process.cwd(), item))); |
||||
|
envConfig = { ...envConfig, ...env }; |
||||
|
} catch (error) {} |
||||
|
}); |
||||
|
|
||||
|
Object.keys(envConfig).forEach((key) => { |
||||
|
const reg = new RegExp(`^(${match})`); |
||||
|
if (!reg.test(key)) { |
||||
|
Reflect.deleteProperty(envConfig, key); |
||||
|
} |
||||
|
}); |
||||
|
return envConfig; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get user root directory |
||||
|
* @param dir file path |
||||
|
*/ |
||||
|
export function getRootPath(...dir: string[]) { |
||||
|
return path.resolve(process.cwd(), ...dir); |
||||
|
} |
@ -0,0 +1,35 @@ |
|||||
|
/** |
||||
|
* Used to package and output gzip. Note that this does not work properly in Vite, the specific reason is still being investigated |
||||
|
* https://github.com/anncwb/vite-plugin-compression
|
||||
|
*/ |
||||
|
import type { Plugin } from 'vite'; |
||||
|
|
||||
|
import compressPlugin from 'vite-plugin-compression'; |
||||
|
|
||||
|
export function configCompressPlugin( |
||||
|
compress: 'gzip' | 'brotli' | 'none', |
||||
|
deleteOriginFile = false |
||||
|
): Plugin | Plugin[] { |
||||
|
const compressList = compress.split(','); |
||||
|
|
||||
|
const plugins: Plugin[] = []; |
||||
|
|
||||
|
if (compressList.includes('gzip')) { |
||||
|
plugins.push( |
||||
|
compressPlugin({ |
||||
|
ext: '.gz', |
||||
|
deleteOriginFile, |
||||
|
}) |
||||
|
); |
||||
|
} |
||||
|
if (compressList.includes('brotli')) { |
||||
|
plugins.push( |
||||
|
compressPlugin({ |
||||
|
ext: '.br', |
||||
|
algorithm: 'brotliCompress', |
||||
|
deleteOriginFile, |
||||
|
}) |
||||
|
); |
||||
|
} |
||||
|
return plugins; |
||||
|
} |
@ -0,0 +1,42 @@ |
|||||
|
/** |
||||
|
* Plugin to minimize and use ejs template syntax in index.html. |
||||
|
* https://github.com/anncwb/vite-plugin-html
|
||||
|
*/ |
||||
|
import type { PluginOption } from 'vite'; |
||||
|
|
||||
|
import { createHtmlPlugin } from 'vite-plugin-html'; |
||||
|
|
||||
|
import pkg from '../../../package.json'; |
||||
|
import { GLOB_CONFIG_FILE_NAME } from '../../constant'; |
||||
|
|
||||
|
export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) { |
||||
|
const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env; |
||||
|
|
||||
|
const path = VITE_PUBLIC_PATH.endsWith('/') ? VITE_PUBLIC_PATH : `${VITE_PUBLIC_PATH}/`; |
||||
|
|
||||
|
const getAppConfigSrc = () => { |
||||
|
return `${path || '/'}${GLOB_CONFIG_FILE_NAME}?v=${pkg.version}-${new Date().getTime()}`; |
||||
|
}; |
||||
|
|
||||
|
const htmlPlugin: PluginOption[] = createHtmlPlugin({ |
||||
|
minify: isBuild, |
||||
|
inject: { |
||||
|
// Inject data into ejs template
|
||||
|
data: { |
||||
|
title: VITE_GLOB_APP_TITLE, |
||||
|
}, |
||||
|
// Embed the generated app.config.js file
|
||||
|
tags: isBuild |
||||
|
? [ |
||||
|
{ |
||||
|
tag: 'script', |
||||
|
attrs: { |
||||
|
src: getAppConfigSrc(), |
||||
|
}, |
||||
|
}, |
||||
|
] |
||||
|
: [], |
||||
|
}, |
||||
|
}); |
||||
|
return htmlPlugin; |
||||
|
} |
@ -0,0 +1,63 @@ |
|||||
|
import type { Plugin, PluginOption } from 'vite'; |
||||
|
import { NaiveUiResolver } from 'unplugin-vue-components/resolvers'; |
||||
|
import AutoImport from 'unplugin-auto-import/vite'; |
||||
|
import Components from 'unplugin-vue-components/vite'; |
||||
|
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'; |
||||
|
|
||||
|
import vue from '@vitejs/plugin-vue'; |
||||
|
import vueJsx from '@vitejs/plugin-vue-jsx'; |
||||
|
|
||||
|
import { configHtmlPlugin } from './html'; |
||||
|
import { configMockPlugin } from './mock'; |
||||
|
import { configCompressPlugin } from './compress'; |
||||
|
|
||||
|
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean, prodMock) { |
||||
|
const { VITE_USE_MOCK, VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE } = viteEnv; |
||||
|
|
||||
|
const vitePlugins: (Plugin | Plugin[] | PluginOption[])[] = [ |
||||
|
// have to
|
||||
|
vue(), |
||||
|
// have to
|
||||
|
vueJsx(), |
||||
|
|
||||
|
AutoImport({ |
||||
|
// 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
|
||||
|
imports: [ |
||||
|
'vue', |
||||
|
'@vueuse/core', |
||||
|
{ |
||||
|
'naive-ui': ['useDialog', 'useMessage', 'useNotification', 'useLoadingBar'], |
||||
|
}, |
||||
|
], |
||||
|
eslintrc: { |
||||
|
enabled: false, // Default `false`
|
||||
|
// filepath: './.eslintrc-auto-import.json', // Default `./.eslintrc-auto-import.json`
|
||||
|
globalsPropValue: true, // Default `true`, (true | false | 'readonly' | 'readable' | 'writable' | 'writeable')
|
||||
|
}, |
||||
|
resolvers: [NaiveUiResolver(), ElementPlusResolver()], |
||||
|
vueTemplate: true, // 是否在 vue 模板中自动导入
|
||||
|
dts: true, |
||||
|
}), |
||||
|
|
||||
|
// 按需引入NaiveUi且自动创建组件声明
|
||||
|
Components({ |
||||
|
dts: true, |
||||
|
resolvers: [NaiveUiResolver(), ElementPlusResolver()], |
||||
|
}), |
||||
|
]; |
||||
|
|
||||
|
// vite-plugin-html
|
||||
|
vitePlugins.push(configHtmlPlugin(viteEnv, isBuild)); |
||||
|
|
||||
|
// vite-plugin-mock
|
||||
|
VITE_USE_MOCK && vitePlugins.push(configMockPlugin(isBuild, prodMock)); |
||||
|
|
||||
|
if (isBuild) { |
||||
|
// rollup-plugin-gzip
|
||||
|
vitePlugins.push( |
||||
|
configCompressPlugin(VITE_BUILD_COMPRESS, VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
return vitePlugins; |
||||
|
} |
@ -0,0 +1,19 @@ |
|||||
|
/** |
||||
|
* Mock plugin for development and production. |
||||
|
* https://github.com/anncwb/vite-plugin-mock
|
||||
|
*/ |
||||
|
import { viteMockServe } from 'vite-plugin-mock'; |
||||
|
|
||||
|
export function configMockPlugin(isBuild: boolean, prodMock: boolean) { |
||||
|
return viteMockServe({ |
||||
|
ignore: /^\_/, |
||||
|
mockPath: 'mock', |
||||
|
localEnabled: !isBuild, |
||||
|
prodEnabled: isBuild && prodMock, |
||||
|
injectCode: ` |
||||
|
import { setupProdMockServer } from '../mock/_createProductionServer'; |
||||
|
|
||||
|
setupProdMockServer(); |
||||
|
`,
|
||||
|
}); |
||||
|
} |
@ -0,0 +1,34 @@ |
|||||
|
/** |
||||
|
* Used to parse the .env.development proxy configuration |
||||
|
*/ |
||||
|
import type { ProxyOptions } from 'vite'; |
||||
|
|
||||
|
type ProxyItem = [string, string]; |
||||
|
|
||||
|
type ProxyList = ProxyItem[]; |
||||
|
|
||||
|
type ProxyTargetList = Record<string, ProxyOptions & { rewrite: (path: string) => string }>; |
||||
|
|
||||
|
const httpsRE = /^https:\/\//; |
||||
|
|
||||
|
/** |
||||
|
* Generate proxy |
||||
|
* @param list |
||||
|
*/ |
||||
|
export function createProxy(list: ProxyList = []) { |
||||
|
const ret: ProxyTargetList = {}; |
||||
|
for (const [prefix, target] of list) { |
||||
|
const isHttps = httpsRE.test(target); |
||||
|
|
||||
|
// https://github.com/http-party/node-http-proxy#options
|
||||
|
ret[prefix] = { |
||||
|
target: target, |
||||
|
changeOrigin: true, |
||||
|
ws: true, |
||||
|
rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ''), |
||||
|
// https is require secure=false
|
||||
|
...(isHttps ? { secure: false } : {}), |
||||
|
}; |
||||
|
} |
||||
|
return ret; |
||||
|
} |
@ -0,0 +1,57 @@ |
|||||
|
module.exports = { |
||||
|
ignores: [(commit) => commit.includes('init')], |
||||
|
extends: ['@commitlint/config-conventional'], |
||||
|
parserPreset: { |
||||
|
parserOpts: { |
||||
|
headerPattern: /^(\w*|[\u4e00-\u9fa5]*)(?:[\(\(](.*)[\)\)])?[\:\:] (.*)/, |
||||
|
headerCorrespondence: ['type', 'scope', 'subject'], |
||||
|
referenceActions: [ |
||||
|
'close', |
||||
|
'closes', |
||||
|
'closed', |
||||
|
'fix', |
||||
|
'fixes', |
||||
|
'fixed', |
||||
|
'resolve', |
||||
|
'resolves', |
||||
|
'resolved', |
||||
|
], |
||||
|
issuePrefixes: ['#'], |
||||
|
noteKeywords: ['BREAKING CHANGE'], |
||||
|
fieldPattern: /^-(.*?)-$/, |
||||
|
revertPattern: /^Revert\s"([\s\S]*)"\s*This reverts commit (\w*)\./, |
||||
|
revertCorrespondence: ['header', 'hash'], |
||||
|
warn() {}, |
||||
|
mergePattern: null, |
||||
|
mergeCorrespondence: null, |
||||
|
}, |
||||
|
}, |
||||
|
rules: { |
||||
|
'body-leading-blank': [2, 'always'], |
||||
|
'footer-leading-blank': [1, 'always'], |
||||
|
'header-max-length': [2, 'always', 108], |
||||
|
'subject-empty': [2, 'never'], |
||||
|
'type-empty': [2, 'never'], |
||||
|
'type-enum': [ |
||||
|
2, |
||||
|
'always', |
||||
|
[ |
||||
|
'feat', |
||||
|
'fix', |
||||
|
'perf', |
||||
|
'style', |
||||
|
'docs', |
||||
|
'test', |
||||
|
'refactor', |
||||
|
'build', |
||||
|
'ci', |
||||
|
'chore', |
||||
|
'revert', |
||||
|
'wip', |
||||
|
'workflow', |
||||
|
'types', |
||||
|
'release', |
||||
|
], |
||||
|
], |
||||
|
}, |
||||
|
}; |
@ -0,0 +1,122 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="zh-cmn-Hans" id="htmlRoot" data-theme="light"> |
||||
|
<head> |
||||
|
<meta charset="UTF-8"> |
||||
|
<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"/> |
||||
|
<meta content="webkit" name="renderer"/> |
||||
|
<meta |
||||
|
content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=0" |
||||
|
name="viewport" |
||||
|
/> |
||||
|
<link href="/favicon.ico" rel="icon"/> |
||||
|
<title><%= title %></title> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div id="appProvider" style="display: none"></div> |
||||
|
<div id="app"> |
||||
|
<style> |
||||
|
.first-loading-wrap { |
||||
|
display: flex; |
||||
|
width: 100%; |
||||
|
height: 100vh; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
flex-direction: column; |
||||
|
} |
||||
|
|
||||
|
.first-loading-wrap > h1 { |
||||
|
font-size: 128px |
||||
|
} |
||||
|
|
||||
|
.first-loading-wrap .loading-wrap { |
||||
|
padding: 98px; |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
align-items: center |
||||
|
} |
||||
|
|
||||
|
.dot { |
||||
|
animation: antRotate 1.2s infinite linear; |
||||
|
transform: rotate(45deg); |
||||
|
position: relative; |
||||
|
display: inline-block; |
||||
|
font-size: 32px; |
||||
|
width: 32px; |
||||
|
height: 32px; |
||||
|
box-sizing: border-box |
||||
|
} |
||||
|
|
||||
|
.dot i { |
||||
|
width: 14px; |
||||
|
height: 14px; |
||||
|
position: absolute; |
||||
|
display: block; |
||||
|
background-color: #1890ff; |
||||
|
border-radius: 100%; |
||||
|
transform: scale(.75); |
||||
|
transform-origin: 50% 50%; |
||||
|
opacity: .3; |
||||
|
animation: antSpinMove 1s infinite linear alternate |
||||
|
} |
||||
|
|
||||
|
.dot i:nth-child(1) { |
||||
|
top: 0; |
||||
|
left: 0 |
||||
|
} |
||||
|
|
||||
|
.dot i:nth-child(2) { |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
-webkit-animation-delay: .4s; |
||||
|
animation-delay: .4s |
||||
|
} |
||||
|
|
||||
|
.dot i:nth-child(3) { |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
-webkit-animation-delay: .8s; |
||||
|
animation-delay: .8s |
||||
|
} |
||||
|
|
||||
|
.dot i:nth-child(4) { |
||||
|
bottom: 0; |
||||
|
left: 0; |
||||
|
-webkit-animation-delay: 1.2s; |
||||
|
animation-delay: 1.2s |
||||
|
} |
||||
|
|
||||
|
@keyframes antRotate { |
||||
|
to { |
||||
|
-webkit-transform: rotate(405deg); |
||||
|
transform: rotate(405deg) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@-webkit-keyframes antRotate { |
||||
|
to { |
||||
|
-webkit-transform: rotate(405deg); |
||||
|
transform: rotate(405deg) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes antSpinMove { |
||||
|
to { |
||||
|
opacity: 1 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@-webkit-keyframes antSpinMove { |
||||
|
to { |
||||
|
opacity: 1 |
||||
|
} |
||||
|
}</style> |
||||
|
<div class="first-loading-wrap"> |
||||
|
<div class="loading-wrap"> |
||||
|
<span class="dot dot-spin"><i></i><i></i><i></i><i></i></span> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
<script>var globalThis = window;</script> |
||||
|
<script src="/src/main.ts" type="module"></script> |
||||
|
</body> |
||||
|
</html> |
@ -0,0 +1,22 @@ |
|||||
|
import { createProdMockServer } from 'vite-plugin-mock/es/createProdMockServer'; |
||||
|
|
||||
|
interface IModuleType { |
||||
|
default: any[]; |
||||
|
} |
||||
|
|
||||
|
const modules = import.meta.glob<IModuleType>('./**/*.ts', { eager: true }); |
||||
|
|
||||
|
const mockModules: any[] = []; |
||||
|
Object.keys(modules).forEach((key) => { |
||||
|
if (key.includes('/_')) { |
||||
|
return; |
||||
|
} |
||||
|
mockModules.push(...modules[key].default); |
||||
|
}); |
||||
|
|
||||
|
/** |
||||
|
* Used in a production environment. Need to manually import all modules |
||||
|
*/ |
||||
|
export function setupProdMockServer() { |
||||
|
createProdMockServer(mockModules); |
||||
|
} |
@ -0,0 +1,73 @@ |
|||||
|
import Mock from 'mockjs'; |
||||
|
|
||||
|
export function resultSuccess(result, { message = 'ok' } = {}) { |
||||
|
return Mock.mock({ |
||||
|
code: 200, |
||||
|
result, |
||||
|
message, |
||||
|
type: 'success', |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
export function resultPageSuccess<T = any>( |
||||
|
page: number, |
||||
|
pageSize: number, |
||||
|
list: T[], |
||||
|
{ message = 'ok' } = {} |
||||
|
) { |
||||
|
const pageData = pagination(page, pageSize, list); |
||||
|
|
||||
|
return { |
||||
|
...resultSuccess({ |
||||
|
page, |
||||
|
pageSize, |
||||
|
pageCount: list.length, |
||||
|
list: pageData, |
||||
|
}), |
||||
|
message, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export function resultError(message = 'Request failed', { code = -1, result = null } = {}) { |
||||
|
return { |
||||
|
code, |
||||
|
result, |
||||
|
message, |
||||
|
type: 'error', |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
export function pagination<T = any>(pageNo: number, pageSize: number, array: T[]): T[] { |
||||
|
const offset = (pageNo - 1) * Number(pageSize); |
||||
|
const ret = |
||||
|
offset + Number(pageSize) >= array.length |
||||
|
? array.slice(offset, array.length) |
||||
|
: array.slice(offset, offset + Number(pageSize)); |
||||
|
return ret; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param {Number} times 回调函数需要执行的次数 |
||||
|
* @param {Function} callback 回调函数 |
||||
|
*/ |
||||
|
export function doCustomTimes(times: number, callback: any) { |
||||
|
let i = -1; |
||||
|
while (++i < times) { |
||||
|
callback(i); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export interface requestParams { |
||||
|
method: string; |
||||
|
body: any; |
||||
|
headers?: { token?: string }; |
||||
|
query: any; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description 本函数用于从request数据中获取token,请根据项目的实际情况修改 |
||||
|
* |
||||
|
*/ |
||||
|
export function getRequestToken({ headers }: requestParams): string | undefined { |
||||
|
return headers?.token; |
||||
|
} |
@ -0,0 +1,44 @@ |
|||||
|
import { Random } from 'mockjs'; |
||||
|
import { resultSuccess } from '../_util'; |
||||
|
|
||||
|
const consoleInfo = { |
||||
|
//访问量
|
||||
|
visits: { |
||||
|
dayVisits: Random.float(10000, 99999, 2, 2), |
||||
|
rise: Random.float(10, 99), |
||||
|
decline: Random.float(10, 99), |
||||
|
amount: Random.float(99999, 999999, 3, 5), |
||||
|
}, |
||||
|
//销售额
|
||||
|
saleroom: { |
||||
|
weekSaleroom: Random.float(10000, 99999, 2, 2), |
||||
|
amount: Random.float(99999, 999999, 2, 2), |
||||
|
degree: Random.float(10, 99), |
||||
|
}, |
||||
|
//订单量
|
||||
|
orderLarge: { |
||||
|
weekLarge: Random.float(10000, 99999, 2, 2), |
||||
|
rise: Random.float(10, 99), |
||||
|
decline: Random.float(10, 99), |
||||
|
amount: Random.float(99999, 999999, 2, 2), |
||||
|
}, |
||||
|
//成交额度
|
||||
|
volume: { |
||||
|
weekLarge: Random.float(10000, 99999, 2, 2), |
||||
|
rise: Random.float(10, 99), |
||||
|
decline: Random.float(10, 99), |
||||
|
amount: Random.float(99999, 999999, 2, 2), |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
export default [ |
||||
|
//主控台 卡片数据
|
||||
|
{ |
||||
|
url: '/api/dashboard/console', |
||||
|
timeout: 1000, |
||||
|
method: 'get', |
||||
|
response: () => { |
||||
|
return resultSuccess(consoleInfo); |
||||
|
}, |
||||
|
}, |
||||
|
]; |
@ -0,0 +1,89 @@ |
|||||
|
import { resultSuccess } from '../_util'; |
||||
|
|
||||
|
const menuList = () => { |
||||
|
const result: any[] = [ |
||||
|
{ |
||||
|
label: 'Dashboard', |
||||
|
key: 'dashboard', |
||||
|
type: 1, |
||||
|
subtitle: 'dashboard', |
||||
|
openType: 1, |
||||
|
auth: 'dashboard', |
||||
|
path: '/dashboard', |
||||
|
children: [ |
||||
|
{ |
||||
|
label: '主控台', |
||||
|
key: 'console', |
||||
|
type: 1, |
||||
|
subtitle: 'console', |
||||
|
openType: 1, |
||||
|
auth: 'console', |
||||
|
path: '/dashboard/console', |
||||
|
}, |
||||
|
{ |
||||
|
label: '工作台', |
||||
|
key: 'workplace', |
||||
|
type: 1, |
||||
|
subtitle: 'workplace', |
||||
|
openType: 1, |
||||
|
auth: 'workplace', |
||||
|
path: '/dashboard/workplace', |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
{ |
||||
|
label: '表单管理', |
||||
|
key: 'form', |
||||
|
type: 1, |
||||
|
subtitle: 'form', |
||||
|
openType: 1, |
||||
|
auth: 'form', |
||||
|
path: '/form', |
||||
|
children: [ |
||||
|
{ |
||||
|
label: '基础表单', |
||||
|
key: 'basic-form', |
||||
|
type: 1, |
||||
|
subtitle: 'basic-form', |
||||
|
openType: 1, |
||||
|
auth: 'basic-form', |
||||
|
path: '/form/basic-form', |
||||
|
}, |
||||
|
{ |
||||
|
label: '分步表单', |
||||
|
key: 'step-form', |
||||
|
type: 1, |
||||
|
subtitle: 'step-form', |
||||
|
openType: 1, |
||||
|
auth: 'step-form', |
||||
|
path: '/form/step-form', |
||||
|
}, |
||||
|
{ |
||||
|
label: '表单详情', |
||||
|
key: 'detail', |
||||
|
type: 1, |
||||
|
subtitle: 'detail', |
||||
|
openType: 1, |
||||
|
auth: 'detail', |
||||
|
path: '/form/detail', |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
return result; |
||||
|
}; |
||||
|
|
||||
|
export default [ |
||||
|
{ |
||||
|
url: '/api/menu/list', |
||||
|
timeout: 1000, |
||||
|
method: 'get', |
||||
|
response: () => { |
||||
|
const list = menuList(); |
||||
|
return resultSuccess({ |
||||
|
list, |
||||
|
}); |
||||
|
}, |
||||
|
}, |
||||
|
]; |
@ -0,0 +1,45 @@ |
|||||
|
import { resultSuccess, doCustomTimes } from '../_util'; |
||||
|
|
||||
|
function getMenuKeys() { |
||||
|
const keys = ['dashboard', 'console', 'workplace', 'basic-form', 'step-form', 'detail']; |
||||
|
const newKeys = []; |
||||
|
doCustomTimes(parseInt(Math.random() * 6), () => { |
||||
|
const key = keys[Math.floor(Math.random() * keys.length)]; |
||||
|
newKeys.push(key); |
||||
|
}); |
||||
|
return Array.from(new Set(newKeys)); |
||||
|
} |
||||
|
|
||||
|
const roleList = (pageSize) => { |
||||
|
const result: any[] = []; |
||||
|
doCustomTimes(pageSize, () => { |
||||
|
result.push({ |
||||
|
id: '@integer(10,100)', |
||||
|
name: '@cname()', |
||||
|
explain: '@cname()', |
||||
|
isDefault: '@boolean()', |
||||
|
menu_keys: getMenuKeys(), |
||||
|
create_date: `@date('yyyy-MM-dd hh:mm:ss')`, |
||||
|
'status|1': ['normal', 'enable', 'disable'], |
||||
|
}); |
||||
|
}); |
||||
|
return result; |
||||
|
}; |
||||
|
|
||||
|
export default [ |
||||
|
{ |
||||
|
url: '/api/role/list', |
||||
|
timeout: 1000, |
||||
|
method: 'get', |
||||
|
response: ({ query }) => { |
||||
|
const { page = 1, pageSize = 10 } = query; |
||||
|
const list = roleList(Number(pageSize)); |
||||
|
return resultSuccess({ |
||||
|
page: Number(page), |
||||
|
pageSize: Number(pageSize), |
||||
|
pageCount: 60, |
||||
|
list, |
||||
|
}); |
||||
|
}, |
||||
|
}, |
||||
|
]; |
@ -0,0 +1,40 @@ |
|||||
|
import { Random } from 'mockjs'; |
||||
|
import { resultSuccess, doCustomTimes } from '../_util'; |
||||
|
|
||||
|
const tableList = (pageSize) => { |
||||
|
const result: any[] = []; |
||||
|
doCustomTimes(pageSize, () => { |
||||
|
result.push({ |
||||
|
id: '@integer(10,999999)', |
||||
|
beginTime: '@datetime', |
||||
|
endTime: '@datetime', |
||||
|
address: '@city()', |
||||
|
name: '@cname()', |
||||
|
avatar: Random.image('400x400', Random.color(), Random.color(), Random.first()), |
||||
|
date: `@date('yyyy-MM-dd')`, |
||||
|
time: `@time('HH:mm')`, |
||||
|
'no|100000-10000000': 100000, |
||||
|
'status|1': [true, false], |
||||
|
}); |
||||
|
}); |
||||
|
return result; |
||||
|
}; |
||||
|
|
||||
|
export default [ |
||||
|
//表格数据列表
|
||||
|
{ |
||||
|
url: '/api/table/list', |
||||
|
timeout: 1000, |
||||
|
method: 'get', |
||||
|
response: ({ query }) => { |
||||
|
const { page = 1, pageSize = 10 } = query; |
||||
|
const list = tableList(Number(pageSize)); |
||||
|
return resultSuccess({ |
||||
|
page: Number(page), |
||||
|
pageSize: Number(pageSize), |
||||
|
pageCount: 60, |
||||
|
list, |
||||
|
}); |
||||
|
}, |
||||
|
}, |
||||
|
]; |
@ -0,0 +1,52 @@ |
|||||
|
import { resultSuccess } from '../_util'; |
||||
|
|
||||
|
const menusList = [ |
||||
|
{ |
||||
|
path: '/dashboard', |
||||
|
name: 'Dashboard', |
||||
|
component: 'LAYOUT', |
||||
|
redirect: '/dashboard/console', |
||||
|
meta: { |
||||
|
icon: 'DashboardOutlined', |
||||
|
title: 'Dashboard', |
||||
|
}, |
||||
|
children: [ |
||||
|
{ |
||||
|
path: 'console', |
||||
|
name: 'dashboard_console', |
||||
|
component: '/dashboard/console/console', |
||||
|
meta: { |
||||
|
title: '主控台', |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
path: 'monitor', |
||||
|
name: 'dashboard_monitor', |
||||
|
component: '/dashboard/monitor/monitor', |
||||
|
meta: { |
||||
|
title: '监控页', |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
path: 'workplace', |
||||
|
name: 'dashboard_workplace', |
||||
|
component: '/dashboard/workplace/workplace', |
||||
|
meta: { |
||||
|
hidden: true, |
||||
|
title: '工作台', |
||||
|
}, |
||||
|
}, |
||||
|
], |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
export default [ |
||||
|
{ |
||||
|
url: '/api/menus', |
||||
|
timeout: 1000, |
||||
|
method: 'get', |
||||
|
response: () => { |
||||
|
return resultSuccess(menusList); |
||||
|
}, |
||||
|
}, |
||||
|
]; |
@ -0,0 +1,157 @@ |
|||||
|
// import Mock from 'mockjs';
|
||||
|
import { resultSuccess } from '../_util'; |
||||
|
|
||||
|
// const Random = Mock.Random;
|
||||
|
|
||||
|
// const token = Random.string('upper', 32, 32);
|
||||
|
|
||||
|
// const adminInfo = {
|
||||
|
// userId: '1',
|
||||
|
// username: 'admin',
|
||||
|
// realName: 'Admin',
|
||||
|
// avatar: Random.image(),
|
||||
|
// desc: 'manager',
|
||||
|
// password: Random.string('upper', 4, 16),
|
||||
|
// token,
|
||||
|
// permissions: [
|
||||
|
// {
|
||||
|
// label: '主控台',
|
||||
|
// value: 'dashboard_console',
|
||||
|
// },
|
||||
|
// {
|
||||
|
// label: '监控页',
|
||||
|
// value: 'dashboard_monitor',
|
||||
|
// },
|
||||
|
// {
|
||||
|
// label: '工作台',
|
||||
|
// value: 'dashboard_workplace',
|
||||
|
// },
|
||||
|
// {
|
||||
|
// label: '基础列表',
|
||||
|
// value: 'basic_list',
|
||||
|
// },
|
||||
|
// {
|
||||
|
// label: '基础列表删除',
|
||||
|
// value: 'basic_list_delete',
|
||||
|
// },
|
||||
|
// ],
|
||||
|
// };
|
||||
|
|
||||
|
const imgCode = { |
||||
|
msg: '操作成功', |
||||
|
img: '/9j/4AAQSkZJRgABAgAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAA8AKADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDtrW1ga1hZoIySikkoOeKsCztv+feL/vgU2z/484P+ua/yqyKiMY8q0IjGPKtCIWdr/wA+0P8A3wKeLK1/59of+/YqQVXl1OxtrpLWe7ginddyRvIFZh7A9apU09kPlj2JhZWn/PrD/wB+xThY2n/PrB/37FV73WdO0yLzL29gt1xnMkgGfp60zRvEOl6+kr6ZdC4WFtrkIy4P4gZ/CrWHk4Ooo+6uttPvC0di8LCz/wCfWD/v2KcLCz/59IP+/YqYU8Vnyx7Byx7EI0+y/wCfS3/79j/CnDTrL/nzt/8Av0v+FTZAqm+uaXDdLayaharOxwIzKN35VUaXNpFXDlj2LI06x/587f8A79L/AIU4abY/8+Vv/wB+l/wqdSDTxU8sewcsexXGmWH/AD5W3/fpf8KeNMsP+fG2/wC/S/4VYFKWVRkkAD1o5Y9g5Y9iAaXp/wDz423/AH5X/CnjStP/AOfC1/78r/hWJdePfC9le/ZJ9atVmzghSWAPuwBA/E10UE8VxEssTq8bDKspyCPatZ4adNKU4WT2utwSi9iIaVp3/Pha/wDflf8ACnDSdO/6B9r/AN+V/wAKtCnisuWPYOWPYqjSdN/6B9p/35X/AAqtqel6fHpF66WNqrrA5VhCoIO08jitYVV1b/kC3/8A17yf+gmlKMeV6ClGPK9DkrP/AI84P+ua/wAqsiq9n/x5wf8AXNf5VZFOPwocfhQjnC5rzH4h6IdauILhJxHLChTay5DDOevavUCuRisjUdHW6ByK6sLiquFqqtRdpIcoqSsz5/utFksoHknuIzt6KmTk/jivT/hZGLPSCyk7rh97enHArJ8Z+HzBpszxrynzflWl8MLuOfSfLyPMgYqw9uor6LF5hicdlLqVHdqdnpsrafiYxgo1LLsdv4q1O+07w3eXWmeX9riTeoddwwD83HrjNUvAPih/EHhuOa7mD3sbtHOcAZOcg4HsRXJeOn8Rx32dLvm+xSr88R2AxnvgkZwfr6+1eYzWD2lxEtxKEjc8yIN238OKzy/LcNisL7KdWKnJ3VruWid4taeqS3HObjK6Wh7T8S73VzpEcOkPINzkTGJsNtx2ryK90tbTSIbxppRes/zo/GOvTvmu08NWWsxP9mmuRf6dKuUkEuTF6cHsfQZ7e9O8R+GIpljEz+Wd3ynIBPtzVYPM/wCzqkMPGSdO93KK1a7NP/h0KUOdX6nd+AvEL3fg62udQkIeFGEkjf3Vzz+WK07z4geFrCDzZNbtJBjhYH81j+C5ryjS/EGoeDJ47a+JudLl+VJMfNH7H1+n5elZ+q2PhfTXW+ENxcQ3DF4kV/3Y74GMYA9Cax/s+hUruc1Jwm7w5EnfV3WtrNeY+dpWXTuelRfGfwxJciJo7+NCcea8K7R78MT+lZ3xS1rWpLa1sdGE5tpwTNJbqTkdhkdB/OvOU8S6KwEU3hu28noWTAfH1wD+td54b1fRtbjh0uxuZBJHH8kE4O4KOwJ4OB7k4HtW+IwTy+pDE08PL3d1K0lto7ra3n+AlLnXK2cvb+FNKGlgXYm+1Mm5pt5Gw/Tp+db/AMJfGUtpfnw3fTb4mJ+yuT90jqufQ9R/9erXjfR5rfw5P9lz5gAJA6le9eeeB7Yz+KLWQNgwuJPfiunCVJY7LcTVxlTmtql/K+jXZPawpLlmlFH1ZGwZQRUoqhpshkt0J9K0BXxp0DhVXVv+QJf/APXtJ/6Catiqur/8gS//AOvaT/0E1MvhZMvhZyVn/wAeUH/XNf5VZFV7L/jyg/65r/KrIoj8KCPwocKdjIpBTxVFHL+JLITW75XIIwRXlGjzXPhLxSXMUhsHbbI+07Qp759q92u7YTxFSK5waG0d3vUd678Fj3hlODjzQmrNfk/VdCZR5rMmvNJXUYQw5DDIIrj9X8GiRGjZTtbuOo9xXqNjB5cKrgAAYAqSaySYcqK4oTlCSnF2a2K3OA8GaFc6VC0Es4mhBzGSuGT1HuKb458Mw6zGkqTPBdRD5HBO0/Uf1616Db2CRdBUGoaWLlDxXRDG14V/rEZWn30/LbXqS4pqx8+apfana2D6bqsCzKeEnB9Oh9/0NWfBkLahHcWUsSywKQ6h1yFb2r0HWPCjzEjZuU9iM1e8MeGvsRA8pVHoFxXq1M6pzwcsOqSjKTTunpful0foQqbUr3MP/hHZNm0wK0f90qCPyq9onhDS4tShvP7OEdxE4dHjd0wfoDivS49Oi2AFBUkenxI2QorxaderTTUJNX3s7XNGk9zn9b0xryzIA7V5JqkbeDtVh1M6bHcRFiNyuY2VvQkZBB+navoR4FaPbiuS1vQ47rMctvHNEx5SRAyn8DWmErwo1VKpHmjs1dq69UKSutDa8J6va63oVrf2jZjmTO09VPdT7g5FdCK5vw5Yx6fbCC3t4oIwc7IkCjP0FdKvSsajg5tw26ehS8xwqrq//IEv/wDr2k/9BNWxVXV/+QJf/wDXtJ/6Cayl8LJl8LOSsv8Ajyt/+ua/yqyK5mLWrmKJI1SIhFCjIPb8ak/t+6/55w/98n/Gso1o2RnGrGyOlFOFcz/wkN3/AM84P++T/jS/8JFd/wDPOD/vk/41Xtoj9tE6gDNHlKTnFcx/wkl5/wA8oP8Avk/40v8Awkt5/wA8oP8Avk/40e2iHtonVqoFSAVyP/CT3v8Azyt/++W/xpf+Eovf+eVv/wB8t/jR7aIe2ideBTsA1x//AAlV9/zyt/8Avlv8aX/hK77/AJ5W3/fLf40e2iHtonWtbI/VRT4rdI+gFch/wlt//wA8bb/vlv8AGl/4S/UP+eNt/wB8t/8AFUe2iHtonbAU8Vw//CYah/zxtf8Avlv/AIql/wCEy1H/AJ42v/fLf/FUe2iHtondAU1oFfqK4j/hM9R/542v/fDf/FUv/Ca6l/zwtP8Avhv/AIqj20Q9tE7mOFU6CpxXAf8ACbal/wA8LT/vhv8A4ql/4TjU/wDnhaf98N/8VR7aIe2iegiqur/8gPUP+vaT/wBBNcV/wnOp/wDPC0/74b/4qo7nxnqN1azW7w2oSVGRiqtkAjHHzVMq0bMUqsbM/9k=', |
||||
|
code: 200, |
||||
|
captchaEnabled: true, |
||||
|
uuid: 'e0f32b7395a44b67b71f8b2c1a590476', |
||||
|
}; |
||||
|
|
||||
|
const loginData = { |
||||
|
msg: '操作成功', |
||||
|
code: 200, |
||||
|
token: |
||||
|
'eyJhbGciOiJIUzUxMiJ9.eyJsb2dpbl91c2VyX2tleSI6ImMyNWQ3ZTBiLWZiZjMtNDAwNy1hNzk2LWM0ZWM5NjI4ZDI2NSJ9.N7U3awYhe6bNedmYRE0ZXO7cvqjqbF7Zd94LMAVZwR866mOvngJ2dRMSx2vcTqjqk25CBafZgIdoZk5ETooyAA', |
||||
|
}; |
||||
|
|
||||
|
const userData = { |
||||
|
msg: '操作成功', |
||||
|
code: 200, |
||||
|
permissions: ['*:*:*'], |
||||
|
roles: ['admin'], |
||||
|
user: { |
||||
|
createBy: 'admin', |
||||
|
createTime: '2021-05-26 18:56:28', |
||||
|
updateBy: null, |
||||
|
updateTime: null, |
||||
|
remark: '管理员', |
||||
|
userId: 1, |
||||
|
deptId: 100, |
||||
|
userName: 'admin', |
||||
|
nickName: '系统管理员', |
||||
|
email: 'ry@163.com', |
||||
|
phonenumber: '15888888888', |
||||
|
sex: '1', |
||||
|
avatar: '', |
||||
|
password: '$2a$10$7JB720yubVSZvUI0rEqK/.VqGOZTH.ulu33dHOiBE8ByOhJIrdAu2', |
||||
|
status: '0', |
||||
|
delFlag: '0', |
||||
|
loginIp: '127.0.0.1', |
||||
|
loginDate: '2023-08-16T08:33:10.356+08:00', |
||||
|
dept: { |
||||
|
createBy: null, |
||||
|
createTime: null, |
||||
|
updateBy: null, |
||||
|
updateTime: null, |
||||
|
remark: null, |
||||
|
deptId: 100, |
||||
|
parentId: 0, |
||||
|
ancestors: '0', |
||||
|
deptName: '联美节能环保集团', |
||||
|
orderNum: 0, |
||||
|
leader: '联美', |
||||
|
phone: null, |
||||
|
email: null, |
||||
|
status: '0', |
||||
|
delFlag: null, |
||||
|
parentName: null, |
||||
|
children: [], |
||||
|
}, |
||||
|
roles: [ |
||||
|
{ |
||||
|
createBy: null, |
||||
|
createTime: null, |
||||
|
updateBy: null, |
||||
|
updateTime: null, |
||||
|
remark: null, |
||||
|
roleId: 1, |
||||
|
roleName: '超级管理员', |
||||
|
roleKey: 'admin', |
||||
|
roleSort: 1, |
||||
|
dataScope: '1', |
||||
|
menuCheckStrictly: false, |
||||
|
deptCheckStrictly: false, |
||||
|
status: '0', |
||||
|
delFlag: null, |
||||
|
flag: false, |
||||
|
menuIds: null, |
||||
|
deptIds: null, |
||||
|
permissions: null, |
||||
|
admin: true, |
||||
|
}, |
||||
|
], |
||||
|
roleIds: null, |
||||
|
postIds: null, |
||||
|
roleId: null, |
||||
|
admin: true, |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
export default [ |
||||
|
{ |
||||
|
url: '/api/captchaImage', |
||||
|
timeout: 1000, |
||||
|
method: 'get', |
||||
|
response: () => { |
||||
|
// const token = getRequestToken(request);
|
||||
|
// if (!token) return resultError('Invalid token');
|
||||
|
return resultSuccess(imgCode); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
url: '/api/login', |
||||
|
timeout: 1000, |
||||
|
method: 'post', |
||||
|
response: () => { |
||||
|
return resultSuccess(loginData); |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
url: '/api/getInfo', |
||||
|
timeout: 1000, |
||||
|
method: 'get', |
||||
|
response: () => { |
||||
|
// const token = getRequestToken(request);
|
||||
|
// if (!token) return resultError('Invalid token');
|
||||
|
return resultSuccess(userData); |
||||
|
}, |
||||
|
}, |
||||
|
]; |
@ -0,0 +1,135 @@ |
|||||
|
{ |
||||
|
"name": "dc-ui-plus", |
||||
|
"version": "1.0.2", |
||||
|
"author": { |
||||
|
"name": "Daniel" |
||||
|
}, |
||||
|
"private": true, |
||||
|
"scripts": { |
||||
|
"bootstrap": "yarn install", |
||||
|
"serve": "npm run dev", |
||||
|
"dev": "vite", |
||||
|
"build": "vite build && esno ./build/script/postBuild.ts", |
||||
|
"build:no-cache": "yarn clean:cache && npm run build", |
||||
|
"report": "cross-env REPORT=true npm run build", |
||||
|
"preview": "npm run build && vite preview", |
||||
|
"preview:dist": "vite preview", |
||||
|
"clean:cache": "rimraf node_modules/.cache/ && rimraf node_modules/.vite", |
||||
|
"clean:lib": "rimraf node_modules", |
||||
|
"build typecheck": "vuedx-typecheck . && vite build", |
||||
|
"deploy": "gh-pages -d dist", |
||||
|
"lint:eslint": "eslint \"{src,mock}/**/*.{vue,ts,tsx}\" --fix", |
||||
|
"lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"", |
||||
|
"lint:stylelint": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/", |
||||
|
"lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js", |
||||
|
"lint:pretty": "pretty-quick --staged", |
||||
|
"test prod gzip": "http-server dist --cors --gzip -c-1" |
||||
|
}, |
||||
|
"dependencies": { |
||||
|
"@vicons/antd": "^0.12.0", |
||||
|
"@vicons/ionicons5": "^0.12.0", |
||||
|
"@vueup/vue-quill": "^1.0.0", |
||||
|
"@vueuse/core": "^9.5.0", |
||||
|
"animate.css": "^4.1.1", |
||||
|
"axios": "^1.1.3", |
||||
|
"blueimp-md5": "^2.19.0", |
||||
|
"date-fns": "^2.29.3", |
||||
|
"echarts": "^5.4.0", |
||||
|
"element-plus": "^2.3.8", |
||||
|
"element-resize-detector": "^1.2.4", |
||||
|
"lodash": "^4.17.21", |
||||
|
"lodash-es": "^4.17.21", |
||||
|
"mitt": "^3.0.1", |
||||
|
"mockjs": "^1.1.0", |
||||
|
"naive-ui": "^2.34.2", |
||||
|
"pinia": "^2.0.23", |
||||
|
"qs": "^6.11.0", |
||||
|
"vfonts": "^0.0.3", |
||||
|
"vue": "^3.2.45", |
||||
|
"vue-router": "^4.1.6", |
||||
|
"vue-types": "^4.2.1", |
||||
|
"vxe-table": "^4.4.2", |
||||
|
"xe-utils": "^3.5.11" |
||||
|
}, |
||||
|
"devDependencies": { |
||||
|
"@commitlint/cli": "^17.2.0", |
||||
|
"@commitlint/config-conventional": "^17.2.0", |
||||
|
"@types/lodash": "^4.14.188", |
||||
|
"@types/node": "^18.11.9", |
||||
|
"@typescript-eslint/eslint-plugin": "^5.42.1", |
||||
|
"@typescript-eslint/parser": "^5.42.1", |
||||
|
"@vicons/tabler": "^0.12.0", |
||||
|
"@vitejs/plugin-vue": "^3.2.0", |
||||
|
"@vitejs/plugin-vue-jsx": "^2.1.1", |
||||
|
"@vue/compiler-sfc": "^3.2.45", |
||||
|
"@vue/eslint-config-typescript": "^11.0.2", |
||||
|
"autoprefixer": "^10.4.13", |
||||
|
"commitizen": "^4.2.5", |
||||
|
"core-js": "^3.26.0", |
||||
|
"dotenv": "^16.0.3", |
||||
|
"eslint": "^8.27.0", |
||||
|
"eslint-config-prettier": "^8.5.0", |
||||
|
"eslint-define-config": "1.12.0", |
||||
|
"eslint-plugin-jest": "^27.1.5", |
||||
|
"eslint-plugin-prettier": "^4.2.1", |
||||
|
"eslint-plugin-vue": "^9.7.0", |
||||
|
"esno": "^0.16.3", |
||||
|
"gh-pages": "^4.0.0", |
||||
|
"husky": "^8.0.2", |
||||
|
"jest": "^29.3.1", |
||||
|
"less": "^4.1.3", |
||||
|
"less-loader": "^11.1.0", |
||||
|
"lint-staged": "^13.0.3", |
||||
|
"postcss": "^8.4.19", |
||||
|
"prettier": "^2.7.1", |
||||
|
"pretty-quick": "^3.1.3", |
||||
|
"rimraf": "^3.0.2", |
||||
|
"stylelint": "^14.14.1", |
||||
|
"stylelint-config-prettier": "^9.0.4", |
||||
|
"stylelint-config-standard": "^29.0.0", |
||||
|
"stylelint-order": "^5.0.0", |
||||
|
"stylelint-scss": "^4.3.0", |
||||
|
"tailwindcss": "^3.2.3", |
||||
|
"typescript": "^4.8.4", |
||||
|
"unplugin-auto-import": "^0.16.6", |
||||
|
"unplugin-vue-components": "^0.22.12", |
||||
|
"vite": "^3.2.3", |
||||
|
"vite-plugin-compression": "^0.5.1", |
||||
|
"vite-plugin-html": "^3.2.0", |
||||
|
"vite-plugin-mock": "^2.9.6", |
||||
|
"vite-plugin-style-import": "^2.0.0", |
||||
|
"vue-demi": "^0.13.11", |
||||
|
"vue-draggable-next": "^2.1.1", |
||||
|
"vue-eslint-parser": "^9.1.0", |
||||
|
"vuedraggable": "^4.1.0" |
||||
|
}, |
||||
|
"lint-staged": { |
||||
|
"*.{vue,js,ts,tsx}": "eslint --fix" |
||||
|
}, |
||||
|
"config": { |
||||
|
"commitizen": { |
||||
|
"path": "./node_modules/cz-customizable" |
||||
|
} |
||||
|
}, |
||||
|
"keywords": [ |
||||
|
"vue", |
||||
|
"naive-ui", |
||||
|
"naive-ui-admin", |
||||
|
"vue3", |
||||
|
"ts", |
||||
|
"tsx", |
||||
|
"admin", |
||||
|
"typescript" |
||||
|
], |
||||
|
"repository": { |
||||
|
"type": "git", |
||||
|
"url": "git+https://github.com/jekip/naive-ui-admin.git" |
||||
|
}, |
||||
|
"license": "MIT", |
||||
|
"bugs": { |
||||
|
"url": "https://github.com/jekip/naive-ui-admin/issues" |
||||
|
}, |
||||
|
"engines": { |
||||
|
"node": "^12 || >=14" |
||||
|
} |
||||
|
} |
@ -0,0 +1,6 @@ |
|||||
|
module.exports = { |
||||
|
plugins: { |
||||
|
tailwindcss: {}, |
||||
|
autoprefixer: {}, |
||||
|
}, |
||||
|
}; |
@ -0,0 +1,20 @@ |
|||||
|
module.exports = { |
||||
|
printWidth: 100, |
||||
|
tabWidth: 2, |
||||
|
useTabs: false, |
||||
|
semi: true, |
||||
|
vueIndentScriptAndStyle: true, |
||||
|
singleQuote: true, |
||||
|
quoteProps: 'as-needed', |
||||
|
bracketSpacing: true, |
||||
|
trailingComma: 'es5', |
||||
|
jsxBracketSameLine: false, |
||||
|
jsxSingleQuote: false, |
||||
|
arrowParens: 'always', |
||||
|
insertPragma: false, |
||||
|
requirePragma: false, |
||||
|
proseWrap: 'never', |
||||
|
htmlWhitespaceSensitivity: 'strict', |
||||
|
endOfLine: 'auto', |
||||
|
rangeStart: 0, |
||||
|
}; |
After Width: | Height: | Size: 2.2 KiB |
@ -0,0 +1,87 @@ |
|||||
|
<template> |
||||
|
<NConfigProvider |
||||
|
v-if="!isLock" |
||||
|
:locale="zhCN" |
||||
|
:theme="getDarkTheme" |
||||
|
:theme-overrides="getThemeOverrides" |
||||
|
:date-locale="dateZhCN" |
||||
|
> |
||||
|
<AppProvider> |
||||
|
<RouterView /> |
||||
|
</AppProvider> |
||||
|
</NConfigProvider> |
||||
|
|
||||
|
<transition v-if="isLock && $route.name !== 'login'" name="slide-up"> |
||||
|
<LockScreen /> |
||||
|
</transition> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { computed, onMounted, onUnmounted } from 'vue'; |
||||
|
import { zhCN, dateZhCN, darkTheme } from 'naive-ui'; |
||||
|
import { LockScreen } from '@/components/Lockscreen'; |
||||
|
import { AppProvider } from '@/components/Application'; |
||||
|
import { useScreenLockStore } from '@/store/modules/screenLock.js'; |
||||
|
import { useRoute } from 'vue-router'; |
||||
|
import { useDesignSettingStore } from '@/store/modules/designSetting'; |
||||
|
import { lighten } from '@/utils/index'; |
||||
|
|
||||
|
const route = useRoute(); |
||||
|
const useScreenLock = useScreenLockStore(); |
||||
|
const designStore = useDesignSettingStore(); |
||||
|
const isLock = computed(() => useScreenLock.isLocked); |
||||
|
const lockTime = computed(() => useScreenLock.lockTime); |
||||
|
|
||||
|
/** |
||||
|
* @type import('naive-ui').GlobalThemeOverrides |
||||
|
*/ |
||||
|
const getThemeOverrides = computed(() => { |
||||
|
const appTheme = designStore.appTheme; |
||||
|
const lightenStr = lighten(designStore.appTheme, 6); |
||||
|
return { |
||||
|
common: { |
||||
|
primaryColor: appTheme, |
||||
|
primaryColorHover: lightenStr, |
||||
|
primaryColorPressed: lightenStr, |
||||
|
primaryColorSuppl: appTheme, |
||||
|
}, |
||||
|
LoadingBar: { |
||||
|
colorLoading: appTheme, |
||||
|
}, |
||||
|
}; |
||||
|
}); |
||||
|
|
||||
|
const getDarkTheme = computed(() => (designStore.darkTheme ? darkTheme : undefined)); |
||||
|
|
||||
|
let timer: NodeJS.Timer; |
||||
|
|
||||
|
const timekeeping = () => { |
||||
|
clearInterval(timer); |
||||
|
if (route.name == 'login' || isLock.value) return; |
||||
|
// 设置不锁屏 |
||||
|
useScreenLock.setLock(false); |
||||
|
// 重置锁屏时间 |
||||
|
useScreenLock.setLockTime(); |
||||
|
timer = setInterval(() => { |
||||
|
// 锁屏倒计时递减 |
||||
|
useScreenLock.setLockTime(lockTime.value - 1); |
||||
|
if (lockTime.value <= 0) { |
||||
|
// 设置锁屏 |
||||
|
useScreenLock.setLock(true); |
||||
|
return clearInterval(timer); |
||||
|
} |
||||
|
}, 1000); |
||||
|
}; |
||||
|
|
||||
|
onMounted(() => { |
||||
|
document.addEventListener('mousedown', timekeeping); |
||||
|
}); |
||||
|
|
||||
|
onUnmounted(() => { |
||||
|
document.removeEventListener('mousedown', timekeeping); |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less"> |
||||
|
@import 'styles/index.less'; |
||||
|
</style> |
@ -0,0 +1,9 @@ |
|||||
|
import { http } from '@/utils/http/axios'; |
||||
|
|
||||
|
//获取主控台信息
|
||||
|
export function getConsoleInfo() { |
||||
|
return http.request({ |
||||
|
url: '/dashboard/console', |
||||
|
method: 'get', |
||||
|
}); |
||||
|
} |
@ -0,0 +1,23 @@ |
|||||
|
import { http } from '@/utils/http/axios'; |
||||
|
|
||||
|
/** |
||||
|
* @description: 根据用户id获取用户菜单 |
||||
|
*/ |
||||
|
export function adminMenus() { |
||||
|
return http.request({ |
||||
|
url: '/menus', |
||||
|
method: 'GET', |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取tree菜单列表 |
||||
|
* @param params |
||||
|
*/ |
||||
|
export function getMenuList(params?) { |
||||
|
return http.request({ |
||||
|
url: '/menu/list', |
||||
|
method: 'GET', |
||||
|
params, |
||||
|
}); |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
import { http } from '@/utils/http/axios'; |
||||
|
|
||||
|
/** |
||||
|
* @description: 角色列表 |
||||
|
*/ |
||||
|
export function getRoleList() { |
||||
|
return http.request({ |
||||
|
url: '/role/list', |
||||
|
method: 'GET', |
||||
|
}); |
||||
|
} |
@ -0,0 +1,87 @@ |
|||||
|
import { http } from '@/utils/http/axios'; |
||||
|
|
||||
|
export interface BasicResponseModel<T = any> { |
||||
|
code: number; |
||||
|
message: string; |
||||
|
result: T; |
||||
|
} |
||||
|
|
||||
|
export interface BasicPageParams { |
||||
|
pageNumber: number; |
||||
|
pageSize: number; |
||||
|
total: number; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* |
||||
|
* @returns 获取验证码 |
||||
|
*/ |
||||
|
export function getCodeImg() { |
||||
|
return http.request( |
||||
|
{ |
||||
|
url: '/captchaImage', |
||||
|
method: 'get', |
||||
|
}, |
||||
|
{ |
||||
|
isTransformResponse: false, |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description: 获取用户信息 |
||||
|
*/ |
||||
|
export function getUserInfo() { |
||||
|
return http.request( |
||||
|
{ |
||||
|
url: '/getInfo', |
||||
|
method: 'get', |
||||
|
}, |
||||
|
{ |
||||
|
isTransformResponse: false, |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description: 用户登录 |
||||
|
*/ |
||||
|
export function login(params) { |
||||
|
return http.request<BasicResponseModel>( |
||||
|
{ |
||||
|
url: '/login', |
||||
|
method: 'POST', |
||||
|
params, |
||||
|
}, |
||||
|
{ |
||||
|
isTransformResponse: false, |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description: 用户修改密码 |
||||
|
*/ |
||||
|
export function changePassword(params, uid) { |
||||
|
return http.request( |
||||
|
{ |
||||
|
url: `/user/u${uid}/changepw`, |
||||
|
method: 'POST', |
||||
|
params, |
||||
|
}, |
||||
|
{ |
||||
|
isTransformResponse: false, |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description: 用户登出 |
||||
|
*/ |
||||
|
export function logout(params) { |
||||
|
return http.request({ |
||||
|
url: '/login/logout', |
||||
|
method: 'POST', |
||||
|
params, |
||||
|
}); |
||||
|
} |
@ -0,0 +1,90 @@ |
|||||
|
import { http } from '@/utils/http/axios'; |
||||
|
|
||||
|
/** |
||||
|
* 获取左侧菜单 |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function getMenu() { |
||||
|
return http.request( |
||||
|
{ |
||||
|
url: '/bi/opt/getMenu', |
||||
|
method: 'get', |
||||
|
}, |
||||
|
{ |
||||
|
isTransformResponse: false, |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取热源信息 |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function getStationInfo() { |
||||
|
return http.request( |
||||
|
{ |
||||
|
url: '/bi/opt/getStationInfo', |
||||
|
method: 'get', |
||||
|
}, |
||||
|
{ |
||||
|
isTransformResponse: false, |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取表格header |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function getTableHeader() { |
||||
|
return http.request( |
||||
|
{ |
||||
|
url: '/bi/opt/getTableHeader', |
||||
|
method: 'get', |
||||
|
}, |
||||
|
{ |
||||
|
isTransformResponse: false, |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 获取表格数据 |
||||
|
* @returns |
||||
|
*/ |
||||
|
export function getTableData(params) { |
||||
|
return http.request( |
||||
|
{ |
||||
|
url: '/bi/opt/getTableData/'+params, |
||||
|
method: 'get', |
||||
|
}, |
||||
|
{ |
||||
|
isTransformResponse: false, |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
//获取table
|
||||
|
export function getTableList(params) { |
||||
|
return http.request({ |
||||
|
url: '/table/list', |
||||
|
method: 'get', |
||||
|
params, |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @description: 配置项修改 |
||||
|
*/ |
||||
|
export function editConfig(params) { |
||||
|
return http.request( |
||||
|
{ |
||||
|
url: '/dc/dcUserMonitorConfig/A', |
||||
|
method: 'POST', |
||||
|
params, |
||||
|
}, |
||||
|
{ |
||||
|
isTransformResponse: false, |
||||
|
} |
||||
|
); |
||||
|
} |
@ -0,0 +1,58 @@ |
|||||
|
/** |
||||
|
* 表格参数 |
||||
|
*/ |
||||
|
export interface TableVo { |
||||
|
id: string; |
||||
|
deviceuuid: string; |
||||
|
areaid: string; |
||||
|
C018: object; |
||||
|
C019: object; |
||||
|
C020: object; |
||||
|
C021: object; |
||||
|
C022: object; |
||||
|
C023: object; |
||||
|
C024: object; |
||||
|
C025: object; |
||||
|
source: string; |
||||
|
data: string; |
||||
|
C007: object; |
||||
|
C026: object; |
||||
|
C027: object; |
||||
|
C028: object; |
||||
|
C029: object; |
||||
|
C005: object; |
||||
|
C006: object; |
||||
|
C001: object; |
||||
|
C002: object; |
||||
|
C003: object; |
||||
|
C004: object; |
||||
|
C008: object; |
||||
|
C009: object; |
||||
|
C010: object; |
||||
|
C011: object; |
||||
|
C012: object; |
||||
|
C013: object; |
||||
|
C014: object; |
||||
|
C015: object; |
||||
|
C016: boolean; |
||||
|
C017: object; |
||||
|
C030: object; |
||||
|
C031: object; |
||||
|
C032: object; |
||||
|
C033: object; |
||||
|
C034: object; |
||||
|
C035: object; |
||||
|
C036: object; |
||||
|
C037: object; |
||||
|
C038: object; |
||||
|
C039: object; |
||||
|
C040: object; |
||||
|
C041: object; |
||||
|
C042: object; |
||||
|
C043: object; |
||||
|
C044: object; |
||||
|
C045: object; |
||||
|
C046: object; |
||||
|
C047: object; |
||||
|
C048: object; |
||||
|
} |
@ -0,0 +1,539 @@ |
|||||
|
/* Logo 字体 */ |
||||
|
@font-face { |
||||
|
font-family: "iconfont logo"; |
||||
|
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); |
||||
|
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'), |
||||
|
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), |
||||
|
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), |
||||
|
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); |
||||
|
} |
||||
|
|
||||
|
.logo { |
||||
|
font-family: "iconfont logo"; |
||||
|
font-size: 160px; |
||||
|
font-style: normal; |
||||
|
-webkit-font-smoothing: antialiased; |
||||
|
-moz-osx-font-smoothing: grayscale; |
||||
|
} |
||||
|
|
||||
|
/* tabs */ |
||||
|
.nav-tabs { |
||||
|
position: relative; |
||||
|
} |
||||
|
|
||||
|
.nav-tabs .nav-more { |
||||
|
position: absolute; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
height: 42px; |
||||
|
line-height: 42px; |
||||
|
color: #666; |
||||
|
} |
||||
|
|
||||
|
#tabs { |
||||
|
border-bottom: 1px solid #eee; |
||||
|
} |
||||
|
|
||||
|
#tabs li { |
||||
|
cursor: pointer; |
||||
|
width: 100px; |
||||
|
height: 40px; |
||||
|
line-height: 40px; |
||||
|
text-align: center; |
||||
|
font-size: 16px; |
||||
|
border-bottom: 2px solid transparent; |
||||
|
position: relative; |
||||
|
z-index: 1; |
||||
|
margin-bottom: -1px; |
||||
|
color: #666; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
#tabs .active { |
||||
|
border-bottom-color: #f00; |
||||
|
color: #222; |
||||
|
} |
||||
|
|
||||
|
.tab-container .content { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
/* 页面布局 */ |
||||
|
.main { |
||||
|
padding: 30px 100px; |
||||
|
width: 960px; |
||||
|
margin: 0 auto; |
||||
|
} |
||||
|
|
||||
|
.main .logo { |
||||
|
color: #333; |
||||
|
text-align: left; |
||||
|
margin-bottom: 30px; |
||||
|
line-height: 1; |
||||
|
height: 110px; |
||||
|
margin-top: -50px; |
||||
|
overflow: hidden; |
||||
|
*zoom: 1; |
||||
|
} |
||||
|
|
||||
|
.main .logo a { |
||||
|
font-size: 160px; |
||||
|
color: #333; |
||||
|
} |
||||
|
|
||||
|
.helps { |
||||
|
margin-top: 40px; |
||||
|
} |
||||
|
|
||||
|
.helps pre { |
||||
|
padding: 20px; |
||||
|
margin: 10px 0; |
||||
|
border: solid 1px #e7e1cd; |
||||
|
background-color: #fffdef; |
||||
|
overflow: auto; |
||||
|
} |
||||
|
|
||||
|
.icon_lists { |
||||
|
width: 100% !important; |
||||
|
overflow: hidden; |
||||
|
*zoom: 1; |
||||
|
} |
||||
|
|
||||
|
.icon_lists li { |
||||
|
width: 100px; |
||||
|
margin-bottom: 10px; |
||||
|
margin-right: 20px; |
||||
|
text-align: center; |
||||
|
list-style: none !important; |
||||
|
cursor: default; |
||||
|
} |
||||
|
|
||||
|
.icon_lists li .code-name { |
||||
|
line-height: 1.2; |
||||
|
} |
||||
|
|
||||
|
.icon_lists .icon { |
||||
|
display: block; |
||||
|
height: 100px; |
||||
|
line-height: 100px; |
||||
|
font-size: 42px; |
||||
|
margin: 10px auto; |
||||
|
color: #333; |
||||
|
-webkit-transition: font-size 0.25s linear, width 0.25s linear; |
||||
|
-moz-transition: font-size 0.25s linear, width 0.25s linear; |
||||
|
transition: font-size 0.25s linear, width 0.25s linear; |
||||
|
} |
||||
|
|
||||
|
.icon_lists .icon:hover { |
||||
|
font-size: 100px; |
||||
|
} |
||||
|
|
||||
|
.icon_lists .svg-icon { |
||||
|
/* 通过设置 font-size 来改变图标大小 */ |
||||
|
width: 1em; |
||||
|
/* 图标和文字相邻时,垂直对齐 */ |
||||
|
vertical-align: -0.15em; |
||||
|
/* 通过设置 color 来改变 SVG 的颜色/fill */ |
||||
|
fill: currentColor; |
||||
|
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 |
||||
|
normalize.css 中也包含这行 */ |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
|
||||
|
.icon_lists li .name, |
||||
|
.icon_lists li .code-name { |
||||
|
color: #666; |
||||
|
} |
||||
|
|
||||
|
/* markdown 样式 */ |
||||
|
.markdown { |
||||
|
color: #666; |
||||
|
font-size: 14px; |
||||
|
line-height: 1.8; |
||||
|
} |
||||
|
|
||||
|
.highlight { |
||||
|
line-height: 1.5; |
||||
|
} |
||||
|
|
||||
|
.markdown img { |
||||
|
vertical-align: middle; |
||||
|
max-width: 100%; |
||||
|
} |
||||
|
|
||||
|
.markdown h1 { |
||||
|
color: #404040; |
||||
|
font-weight: 500; |
||||
|
line-height: 40px; |
||||
|
margin-bottom: 24px; |
||||
|
} |
||||
|
|
||||
|
.markdown h2, |
||||
|
.markdown h3, |
||||
|
.markdown h4, |
||||
|
.markdown h5, |
||||
|
.markdown h6 { |
||||
|
color: #404040; |
||||
|
margin: 1.6em 0 0.6em 0; |
||||
|
font-weight: 500; |
||||
|
clear: both; |
||||
|
} |
||||
|
|
||||
|
.markdown h1 { |
||||
|
font-size: 28px; |
||||
|
} |
||||
|
|
||||
|
.markdown h2 { |
||||
|
font-size: 22px; |
||||
|
} |
||||
|
|
||||
|
.markdown h3 { |
||||
|
font-size: 16px; |
||||
|
} |
||||
|
|
||||
|
.markdown h4 { |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
|
||||
|
.markdown h5 { |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
|
||||
|
.markdown h6 { |
||||
|
font-size: 12px; |
||||
|
} |
||||
|
|
||||
|
.markdown hr { |
||||
|
height: 1px; |
||||
|
border: 0; |
||||
|
background: #e9e9e9; |
||||
|
margin: 16px 0; |
||||
|
clear: both; |
||||
|
} |
||||
|
|
||||
|
.markdown p { |
||||
|
margin: 1em 0; |
||||
|
} |
||||
|
|
||||
|
.markdown>p, |
||||
|
.markdown>blockquote, |
||||
|
.markdown>.highlight, |
||||
|
.markdown>ol, |
||||
|
.markdown>ul { |
||||
|
width: 80%; |
||||
|
} |
||||
|
|
||||
|
.markdown ul>li { |
||||
|
list-style: circle; |
||||
|
} |
||||
|
|
||||
|
.markdown>ul li, |
||||
|
.markdown blockquote ul>li { |
||||
|
margin-left: 20px; |
||||
|
padding-left: 4px; |
||||
|
} |
||||
|
|
||||
|
.markdown>ul li p, |
||||
|
.markdown>ol li p { |
||||
|
margin: 0.6em 0; |
||||
|
} |
||||
|
|
||||
|
.markdown ol>li { |
||||
|
list-style: decimal; |
||||
|
} |
||||
|
|
||||
|
.markdown>ol li, |
||||
|
.markdown blockquote ol>li { |
||||
|
margin-left: 20px; |
||||
|
padding-left: 4px; |
||||
|
} |
||||
|
|
||||
|
.markdown code { |
||||
|
margin: 0 3px; |
||||
|
padding: 0 5px; |
||||
|
background: #eee; |
||||
|
border-radius: 3px; |
||||
|
} |
||||
|
|
||||
|
.markdown strong, |
||||
|
.markdown b { |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
|
||||
|
.markdown>table { |
||||
|
border-collapse: collapse; |
||||
|
border-spacing: 0px; |
||||
|
empty-cells: show; |
||||
|
border: 1px solid #e9e9e9; |
||||
|
width: 95%; |
||||
|
margin-bottom: 24px; |
||||
|
} |
||||
|
|
||||
|
.markdown>table th { |
||||
|
white-space: nowrap; |
||||
|
color: #333; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
|
||||
|
.markdown>table th, |
||||
|
.markdown>table td { |
||||
|
border: 1px solid #e9e9e9; |
||||
|
padding: 8px 16px; |
||||
|
text-align: left; |
||||
|
} |
||||
|
|
||||
|
.markdown>table th { |
||||
|
background: #F7F7F7; |
||||
|
} |
||||
|
|
||||
|
.markdown blockquote { |
||||
|
font-size: 90%; |
||||
|
color: #999; |
||||
|
border-left: 4px solid #e9e9e9; |
||||
|
padding-left: 0.8em; |
||||
|
margin: 1em 0; |
||||
|
} |
||||
|
|
||||
|
.markdown blockquote p { |
||||
|
margin: 0; |
||||
|
} |
||||
|
|
||||
|
.markdown .anchor { |
||||
|
opacity: 0; |
||||
|
transition: opacity 0.3s ease; |
||||
|
margin-left: 8px; |
||||
|
} |
||||
|
|
||||
|
.markdown .waiting { |
||||
|
color: #ccc; |
||||
|
} |
||||
|
|
||||
|
.markdown h1:hover .anchor, |
||||
|
.markdown h2:hover .anchor, |
||||
|
.markdown h3:hover .anchor, |
||||
|
.markdown h4:hover .anchor, |
||||
|
.markdown h5:hover .anchor, |
||||
|
.markdown h6:hover .anchor { |
||||
|
opacity: 1; |
||||
|
display: inline-block; |
||||
|
} |
||||
|
|
||||
|
.markdown>br, |
||||
|
.markdown>p>br { |
||||
|
clear: both; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
.hljs { |
||||
|
display: block; |
||||
|
background: white; |
||||
|
padding: 0.5em; |
||||
|
color: #333333; |
||||
|
overflow-x: auto; |
||||
|
} |
||||
|
|
||||
|
.hljs-comment, |
||||
|
.hljs-meta { |
||||
|
color: #969896; |
||||
|
} |
||||
|
|
||||
|
.hljs-string, |
||||
|
.hljs-variable, |
||||
|
.hljs-template-variable, |
||||
|
.hljs-strong, |
||||
|
.hljs-emphasis, |
||||
|
.hljs-quote { |
||||
|
color: #df5000; |
||||
|
} |
||||
|
|
||||
|
.hljs-keyword, |
||||
|
.hljs-selector-tag, |
||||
|
.hljs-type { |
||||
|
color: #a71d5d; |
||||
|
} |
||||
|
|
||||
|
.hljs-literal, |
||||
|
.hljs-symbol, |
||||
|
.hljs-bullet, |
||||
|
.hljs-attribute { |
||||
|
color: #0086b3; |
||||
|
} |
||||
|
|
||||
|
.hljs-section, |
||||
|
.hljs-name { |
||||
|
color: #63a35c; |
||||
|
} |
||||
|
|
||||
|
.hljs-tag { |
||||
|
color: #333333; |
||||
|
} |
||||
|
|
||||
|
.hljs-title, |
||||
|
.hljs-attr, |
||||
|
.hljs-selector-id, |
||||
|
.hljs-selector-class, |
||||
|
.hljs-selector-attr, |
||||
|
.hljs-selector-pseudo { |
||||
|
color: #795da3; |
||||
|
} |
||||
|
|
||||
|
.hljs-addition { |
||||
|
color: #55a532; |
||||
|
background-color: #eaffea; |
||||
|
} |
||||
|
|
||||
|
.hljs-deletion { |
||||
|
color: #bd2c00; |
||||
|
background-color: #ffecec; |
||||
|
} |
||||
|
|
||||
|
.hljs-link { |
||||
|
text-decoration: underline; |
||||
|
} |
||||
|
|
||||
|
/* 代码高亮 */ |
||||
|
/* PrismJS 1.15.0 |
||||
|
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */ |
||||
|
/** |
||||
|
* prism.js default theme for JavaScript, CSS and HTML |
||||
|
* Based on dabblet (http://dabblet.com) |
||||
|
* @author Lea Verou |
||||
|
*/ |
||||
|
code[class*="language-"], |
||||
|
pre[class*="language-"] { |
||||
|
color: black; |
||||
|
background: none; |
||||
|
text-shadow: 0 1px white; |
||||
|
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; |
||||
|
text-align: left; |
||||
|
white-space: pre; |
||||
|
word-spacing: normal; |
||||
|
word-break: normal; |
||||
|
word-wrap: normal; |
||||
|
line-height: 1.5; |
||||
|
|
||||
|
-moz-tab-size: 4; |
||||
|
-o-tab-size: 4; |
||||
|
tab-size: 4; |
||||
|
|
||||
|
-webkit-hyphens: none; |
||||
|
-moz-hyphens: none; |
||||
|
-ms-hyphens: none; |
||||
|
hyphens: none; |
||||
|
} |
||||
|
|
||||
|
pre[class*="language-"]::-moz-selection, |
||||
|
pre[class*="language-"] ::-moz-selection, |
||||
|
code[class*="language-"]::-moz-selection, |
||||
|
code[class*="language-"] ::-moz-selection { |
||||
|
text-shadow: none; |
||||
|
background: #b3d4fc; |
||||
|
} |
||||
|
|
||||
|
pre[class*="language-"]::selection, |
||||
|
pre[class*="language-"] ::selection, |
||||
|
code[class*="language-"]::selection, |
||||
|
code[class*="language-"] ::selection { |
||||
|
text-shadow: none; |
||||
|
background: #b3d4fc; |
||||
|
} |
||||
|
|
||||
|
@media print { |
||||
|
|
||||
|
code[class*="language-"], |
||||
|
pre[class*="language-"] { |
||||
|
text-shadow: none; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/* Code blocks */ |
||||
|
pre[class*="language-"] { |
||||
|
padding: 1em; |
||||
|
margin: .5em 0; |
||||
|
overflow: auto; |
||||
|
} |
||||
|
|
||||
|
:not(pre)>code[class*="language-"], |
||||
|
pre[class*="language-"] { |
||||
|
background: #f5f2f0; |
||||
|
} |
||||
|
|
||||
|
/* Inline code */ |
||||
|
:not(pre)>code[class*="language-"] { |
||||
|
padding: .1em; |
||||
|
border-radius: .3em; |
||||
|
white-space: normal; |
||||
|
} |
||||
|
|
||||
|
.token.comment, |
||||
|
.token.prolog, |
||||
|
.token.doctype, |
||||
|
.token.cdata { |
||||
|
color: slategray; |
||||
|
} |
||||
|
|
||||
|
.token.punctuation { |
||||
|
color: #999; |
||||
|
} |
||||
|
|
||||
|
.namespace { |
||||
|
opacity: .7; |
||||
|
} |
||||
|
|
||||
|
.token.property, |
||||
|
.token.tag, |
||||
|
.token.boolean, |
||||
|
.token.number, |
||||
|
.token.constant, |
||||
|
.token.symbol, |
||||
|
.token.deleted { |
||||
|
color: #905; |
||||
|
} |
||||
|
|
||||
|
.token.selector, |
||||
|
.token.attr-name, |
||||
|
.token.string, |
||||
|
.token.char, |
||||
|
.token.builtin, |
||||
|
.token.inserted { |
||||
|
color: #690; |
||||
|
} |
||||
|
|
||||
|
.token.operator, |
||||
|
.token.entity, |
||||
|
.token.url, |
||||
|
.language-css .token.string, |
||||
|
.style .token.string { |
||||
|
color: #9a6e3a; |
||||
|
background: hsla(0, 0%, 100%, .5); |
||||
|
} |
||||
|
|
||||
|
.token.atrule, |
||||
|
.token.attr-value, |
||||
|
.token.keyword { |
||||
|
color: #07a; |
||||
|
} |
||||
|
|
||||
|
.token.function, |
||||
|
.token.class-name { |
||||
|
color: #DD4A68; |
||||
|
} |
||||
|
|
||||
|
.token.regex, |
||||
|
.token.important, |
||||
|
.token.variable { |
||||
|
color: #e90; |
||||
|
} |
||||
|
|
||||
|
.token.important, |
||||
|
.token.bold { |
||||
|
font-weight: bold; |
||||
|
} |
||||
|
|
||||
|
.token.italic { |
||||
|
font-style: italic; |
||||
|
} |
||||
|
|
||||
|
.token.entity { |
||||
|
cursor: help; |
||||
|
} |
@ -0,0 +1,230 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html> |
||||
|
<head> |
||||
|
<meta charset="utf-8"/> |
||||
|
<title>iconfont Demo</title> |
||||
|
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg" type="image/x-icon"/> |
||||
|
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01Z5paLz1O0zuCC7osS_!!6000000001644-55-tps-83-82.svg"/> |
||||
|
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css"> |
||||
|
<link rel="stylesheet" href="demo.css"> |
||||
|
<link rel="stylesheet" href="iconfont.css"> |
||||
|
<script src="iconfont.js"></script> |
||||
|
<!-- jQuery --> |
||||
|
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script> |
||||
|
<!-- 代码高亮 --> |
||||
|
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script> |
||||
|
<style> |
||||
|
.main .logo { |
||||
|
margin-top: 0; |
||||
|
height: auto; |
||||
|
} |
||||
|
|
||||
|
.main .logo a { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
} |
||||
|
|
||||
|
.main .logo .sub-title { |
||||
|
margin-left: 0.5em; |
||||
|
font-size: 22px; |
||||
|
color: #fff; |
||||
|
background: linear-gradient(-45deg, #3967FF, #B500FE); |
||||
|
-webkit-background-clip: text; |
||||
|
-webkit-text-fill-color: transparent; |
||||
|
} |
||||
|
</style> |
||||
|
</head> |
||||
|
<body> |
||||
|
<div class="main"> |
||||
|
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank"> |
||||
|
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg"> |
||||
|
|
||||
|
</a></h1> |
||||
|
<div class="nav-tabs"> |
||||
|
<ul id="tabs" class="dib-box"> |
||||
|
<li class="dib active"><span>Unicode</span></li> |
||||
|
<li class="dib"><span>Font class</span></li> |
||||
|
<li class="dib"><span>Symbol</span></li> |
||||
|
</ul> |
||||
|
|
||||
|
</div> |
||||
|
<div class="tab-container"> |
||||
|
<div class="content unicode" style="display: block;"> |
||||
|
<ul class="icon_lists dib-box"> |
||||
|
|
||||
|
<li class="dib"> |
||||
|
<span class="icon iconfont"></span> |
||||
|
<div class="name">箭头_切换向下</div> |
||||
|
<div class="code-name">&#xeb04;</div> |
||||
|
</li> |
||||
|
|
||||
|
<li class="dib"> |
||||
|
<span class="icon iconfont"></span> |
||||
|
<div class="name">箭头_切换向上</div> |
||||
|
<div class="code-name">&#xeb05;</div> |
||||
|
</li> |
||||
|
|
||||
|
</ul> |
||||
|
<div class="article markdown"> |
||||
|
<h2 id="unicode-">Unicode 引用</h2> |
||||
|
<hr> |
||||
|
|
||||
|
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p> |
||||
|
<ul> |
||||
|
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li> |
||||
|
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li> |
||||
|
</ul> |
||||
|
<blockquote> |
||||
|
<p>注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p> |
||||
|
</blockquote> |
||||
|
<p>Unicode 使用步骤如下:</p> |
||||
|
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3> |
||||
|
<pre><code class="language-css" |
||||
|
>@font-face { |
||||
|
font-family: 'iconfont'; |
||||
|
src: url('iconfont.ttf?t=1692926138640') format('truetype'); |
||||
|
} |
||||
|
</code></pre> |
||||
|
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3> |
||||
|
<pre><code class="language-css" |
||||
|
>.iconfont { |
||||
|
font-family: "iconfont" !important; |
||||
|
font-size: 16px; |
||||
|
font-style: normal; |
||||
|
-webkit-font-smoothing: antialiased; |
||||
|
-moz-osx-font-smoothing: grayscale; |
||||
|
} |
||||
|
</code></pre> |
||||
|
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3> |
||||
|
<pre> |
||||
|
<code class="language-html" |
||||
|
><span class="iconfont">&#x33;</span> |
||||
|
</code></pre> |
||||
|
<blockquote> |
||||
|
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p> |
||||
|
</blockquote> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="content font-class"> |
||||
|
<ul class="icon_lists dib-box"> |
||||
|
|
||||
|
<li class="dib"> |
||||
|
<span class="icon iconfont icon-decline"></span> |
||||
|
<div class="name"> |
||||
|
箭头_切换向下 |
||||
|
</div> |
||||
|
<div class="code-name">.icon-decline |
||||
|
</div> |
||||
|
</li> |
||||
|
|
||||
|
<li class="dib"> |
||||
|
<span class="icon iconfont icon-rise"></span> |
||||
|
<div class="name"> |
||||
|
箭头_切换向上 |
||||
|
</div> |
||||
|
<div class="code-name">.icon-rise |
||||
|
</div> |
||||
|
</li> |
||||
|
|
||||
|
</ul> |
||||
|
<div class="article markdown"> |
||||
|
<h2 id="font-class-">font-class 引用</h2> |
||||
|
<hr> |
||||
|
|
||||
|
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p> |
||||
|
<p>与 Unicode 使用方式相比,具有如下特点:</p> |
||||
|
<ul> |
||||
|
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li> |
||||
|
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li> |
||||
|
</ul> |
||||
|
<p>使用步骤如下:</p> |
||||
|
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3> |
||||
|
<pre><code class="language-html"><link rel="stylesheet" href="./iconfont.css"> |
||||
|
</code></pre> |
||||
|
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3> |
||||
|
<pre><code class="language-html"><span class="iconfont icon-xxx"></span> |
||||
|
</code></pre> |
||||
|
<blockquote> |
||||
|
<p>" |
||||
|
iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p> |
||||
|
</blockquote> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="content symbol"> |
||||
|
<ul class="icon_lists dib-box"> |
||||
|
|
||||
|
<li class="dib"> |
||||
|
<svg class="icon svg-icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-decline"></use> |
||||
|
</svg> |
||||
|
<div class="name">箭头_切换向下</div> |
||||
|
<div class="code-name">#icon-decline</div> |
||||
|
</li> |
||||
|
|
||||
|
<li class="dib"> |
||||
|
<svg class="icon svg-icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-rise"></use> |
||||
|
</svg> |
||||
|
<div class="name">箭头_切换向上</div> |
||||
|
<div class="code-name">#icon-rise</div> |
||||
|
</li> |
||||
|
|
||||
|
</ul> |
||||
|
<div class="article markdown"> |
||||
|
<h2 id="symbol-">Symbol 引用</h2> |
||||
|
<hr> |
||||
|
|
||||
|
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a> |
||||
|
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p> |
||||
|
<ul> |
||||
|
<li>支持多色图标了,不再受单色限制。</li> |
||||
|
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li> |
||||
|
<li>兼容性较差,支持 IE9+,及现代浏览器。</li> |
||||
|
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li> |
||||
|
</ul> |
||||
|
<p>使用步骤如下:</p> |
||||
|
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3> |
||||
|
<pre><code class="language-html"><script src="./iconfont.js"></script> |
||||
|
</code></pre> |
||||
|
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3> |
||||
|
<pre><code class="language-html"><style> |
||||
|
.icon { |
||||
|
width: 1em; |
||||
|
height: 1em; |
||||
|
vertical-align: -0.15em; |
||||
|
fill: currentColor; |
||||
|
overflow: hidden; |
||||
|
} |
||||
|
</style> |
||||
|
</code></pre> |
||||
|
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3> |
||||
|
<pre><code class="language-html"><svg class="icon" aria-hidden="true"> |
||||
|
<use xlink:href="#icon-xxx"></use> |
||||
|
</svg> |
||||
|
</code></pre> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
<script> |
||||
|
$(document).ready(function () { |
||||
|
$('.tab-container .content:first').show() |
||||
|
|
||||
|
$('#tabs li').click(function (e) { |
||||
|
var tabContent = $('.tab-container .content') |
||||
|
var index = $(this).index() |
||||
|
|
||||
|
if ($(this).hasClass('active')) { |
||||
|
return |
||||
|
} else { |
||||
|
$('#tabs li').removeClass('active') |
||||
|
$(this).addClass('active') |
||||
|
|
||||
|
tabContent.hide().eq(index).fadeIn() |
||||
|
} |
||||
|
}) |
||||
|
}) |
||||
|
</script> |
||||
|
</body> |
||||
|
</html> |
@ -0,0 +1,21 @@ |
|||||
|
@font-face { |
||||
|
font-family: "iconfont"; /* Project id */ |
||||
|
src: url('iconfont.ttf?t=1692926138640') format('truetype'); |
||||
|
} |
||||
|
|
||||
|
.iconfont { |
||||
|
font-family: "iconfont" !important; |
||||
|
font-size: 16px; |
||||
|
font-style: normal; |
||||
|
-webkit-font-smoothing: antialiased; |
||||
|
-moz-osx-font-smoothing: grayscale; |
||||
|
} |
||||
|
|
||||
|
.icon-decline:before { |
||||
|
content: "\eb04"; |
||||
|
} |
||||
|
|
||||
|
.icon-rise:before { |
||||
|
content: "\eb05"; |
||||
|
} |
||||
|
|
@ -0,0 +1 @@ |
|||||
|
window._iconfont_svg_string_='<svg><symbol id="icon-decline" viewBox="0 0 1024 1024"><path d="M538.51148682 873.04849423L326.20720947 660.74421688l62.13783703-62.13783704 150.16644032 150.16644032V44.544H636.89639465v932.06755556l-98.38490783-103.56306133z" fill="#444444" ></path></symbol><symbol id="icon-rise" viewBox="0 0 1024 1024"><path d="M484.06629095 154.70743703l212.30427736 207.12612387-62.13783704 62.13783704-150.16644032-150.16644032V978.03377778H385.68138313V45.96622222l98.38490782 108.74121481z" fill="#444444" ></path></symbol></svg>',function(n){var e=(e=document.getElementsByTagName("script"))[e.length-1],t=e.getAttribute("data-injectcss"),e=e.getAttribute("data-disable-injectsvg");if(!e){var i,o,d,c,l,s=function(e,t){t.parentNode.insertBefore(e,t)};if(t&&!n.__iconfont__svg__cssinject__){n.__iconfont__svg__cssinject__=!0;try{document.write("<style>.svgfont {display: inline-block;width: 1em;height: 1em;fill: currentColor;vertical-align: -0.1em;font-size:16px;}</style>")}catch(e){console&&console.log(e)}}i=function(){var e,t=document.createElement("div");t.innerHTML=n._iconfont_svg_string_,(t=t.getElementsByTagName("svg")[0])&&(t.setAttribute("aria-hidden","true"),t.style.position="absolute",t.style.width=0,t.style.height=0,t.style.overflow="hidden",t=t,(e=document.body).firstChild?s(t,e.firstChild):e.appendChild(t))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(i,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),i()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(d=i,c=n.document,l=!1,r(),c.onreadystatechange=function(){"complete"==c.readyState&&(c.onreadystatechange=null,a())})}function a(){l||(l=!0,d())}function r(){try{c.documentElement.doScroll("left")}catch(e){return void setTimeout(r,50)}a()}}(window); |
@ -0,0 +1,23 @@ |
|||||
|
{ |
||||
|
"id": "", |
||||
|
"name": "", |
||||
|
"font_family": "iconfont", |
||||
|
"css_prefix_text": "icon-", |
||||
|
"description": "", |
||||
|
"glyphs": [ |
||||
|
{ |
||||
|
"icon_id": "122793502", |
||||
|
"name": "箭头_切换向下", |
||||
|
"font_class": "decline", |
||||
|
"unicode": "eb04", |
||||
|
"unicode_decimal": 60164 |
||||
|
}, |
||||
|
{ |
||||
|
"icon_id": "122793503", |
||||
|
"name": "箭头_切换向上", |
||||
|
"font_class": "rise", |
||||
|
"unicode": "eb05", |
||||
|
"unicode_decimal": 60165 |
||||
|
} |
||||
|
] |
||||
|
} |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 48 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 34 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 33 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 123 KiB |
After Width: | Height: | Size: 177 KiB |
After Width: | Height: | Size: 2.6 KiB |
@ -0,0 +1,26 @@ |
|||||
|
<template> |
||||
|
<n-dialog-provider> |
||||
|
<n-notification-provider> |
||||
|
<n-message-provider> |
||||
|
<slot name="default"></slot> |
||||
|
</n-message-provider> |
||||
|
</n-notification-provider> |
||||
|
</n-dialog-provider> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
import { defineComponent } from 'vue'; |
||||
|
import { NDialogProvider, NNotificationProvider, NMessageProvider } from 'naive-ui'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
name: 'Application', |
||||
|
components: { |
||||
|
NDialogProvider, |
||||
|
NNotificationProvider, |
||||
|
NMessageProvider, |
||||
|
}, |
||||
|
setup() { |
||||
|
return {}; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
@ -0,0 +1,3 @@ |
|||||
|
import AppProvider from './Application.vue'; |
||||
|
|
||||
|
export { AppProvider }; |
@ -0,0 +1,110 @@ |
|||||
|
<template> |
||||
|
<span :style="{ color }"> |
||||
|
{{ value }} |
||||
|
</span> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import { defineComponent, ref, computed, watchEffect, unref, onMounted, watch } from 'vue'; |
||||
|
import { useTransition, TransitionPresets } from '@vueuse/core'; |
||||
|
import { isNumber } from '@/utils/is'; |
||||
|
|
||||
|
const props = { |
||||
|
startVal: { type: Number, default: 0 }, |
||||
|
endVal: { type: Number, default: 2021 }, |
||||
|
duration: { type: Number, default: 1500 }, |
||||
|
autoplay: { type: Boolean, default: true }, |
||||
|
decimals: { |
||||
|
type: Number, |
||||
|
default: 0, |
||||
|
validator(value: number) { |
||||
|
return value >= 0; |
||||
|
}, |
||||
|
}, |
||||
|
prefix: { type: String, default: '' }, |
||||
|
suffix: { type: String, default: '' }, |
||||
|
separator: { type: String, default: ',' }, |
||||
|
decimal: { type: String, default: '.' }, |
||||
|
/** |
||||
|
* font color |
||||
|
*/ |
||||
|
color: { type: String }, |
||||
|
/** |
||||
|
* Turn on digital animation |
||||
|
*/ |
||||
|
useEasing: { type: Boolean, default: true }, |
||||
|
/** |
||||
|
* Digital animation |
||||
|
*/ |
||||
|
transition: { type: String, default: 'linear' }, |
||||
|
}; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
name: 'CountTo', |
||||
|
props, |
||||
|
emits: ['onStarted', 'onFinished'], |
||||
|
setup(props, { emit }) { |
||||
|
const source = ref(props.startVal); |
||||
|
const disabled = ref(false); |
||||
|
let outputValue = useTransition(source); |
||||
|
|
||||
|
const value = computed(() => formatNumber(unref(outputValue))); |
||||
|
|
||||
|
watchEffect(() => { |
||||
|
source.value = props.startVal; |
||||
|
}); |
||||
|
|
||||
|
watch([() => props.startVal, () => props.endVal], () => { |
||||
|
if (props.autoplay) { |
||||
|
start(); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
onMounted(() => { |
||||
|
props.autoplay && start(); |
||||
|
}); |
||||
|
|
||||
|
function start() { |
||||
|
run(); |
||||
|
source.value = props.endVal; |
||||
|
} |
||||
|
|
||||
|
function reset() { |
||||
|
source.value = props.startVal; |
||||
|
run(); |
||||
|
} |
||||
|
|
||||
|
function run() { |
||||
|
outputValue = useTransition(source, { |
||||
|
disabled, |
||||
|
duration: props.duration, |
||||
|
onFinished: () => emit('onFinished'), |
||||
|
onStarted: () => emit('onStarted'), |
||||
|
...(props.useEasing ? { transition: TransitionPresets[props.transition] } : {}), |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function formatNumber(num: number | string) { |
||||
|
if (!num) { |
||||
|
return ''; |
||||
|
} |
||||
|
const { decimals, decimal, separator, suffix, prefix } = props; |
||||
|
num = Number(num).toFixed(decimals); |
||||
|
num += ''; |
||||
|
|
||||
|
const x = num.split('.'); |
||||
|
let x1 = x[0]; |
||||
|
const x2 = x.length > 1 ? decimal + x[1] : ''; |
||||
|
|
||||
|
const rgx = /(\d+)(\d{3})/; |
||||
|
if (separator && !isNumber(separator)) { |
||||
|
while (rgx.test(x1)) { |
||||
|
x1 = x1.replace(rgx, '$1' + separator + '$2'); |
||||
|
} |
||||
|
} |
||||
|
return prefix + x1 + x2 + suffix; |
||||
|
} |
||||
|
|
||||
|
return { value, start, reset }; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
@ -0,0 +1,4 @@ |
|||||
|
import { withInstall } from '@/utils'; |
||||
|
import countTo from './CountTo.vue'; |
||||
|
|
||||
|
export const CountTo = withInstall(countTo); |
@ -0,0 +1,4 @@ |
|||||
|
export { default as BasicForm } from './src/BasicForm.vue'; |
||||
|
export { useForm } from './src/hooks/useForm'; |
||||
|
export * from './src/types/form'; |
||||
|
export * from './src/types/index'; |
@ -0,0 +1,318 @@ |
|||||
|
<template> |
||||
|
<n-form v-bind="getBindValue" :model="formModel" ref="formElRef"> |
||||
|
<n-grid v-bind="getGrid"> |
||||
|
<n-gi v-bind="schema.giProps" v-for="schema in getSchema" :key="schema.field"> |
||||
|
<n-form-item :label="schema.label" :path="schema.field"> |
||||
|
<!--标签名右侧温馨提示--> |
||||
|
<template #label v-if="schema.labelMessage"> |
||||
|
{{ schema.label }} |
||||
|
<n-tooltip trigger="hover" :style="schema.labelMessageStyle"> |
||||
|
<template #trigger> |
||||
|
<n-icon size="18" class="cursor-pointer text-gray-400"> |
||||
|
<QuestionCircleOutlined /> |
||||
|
</n-icon> |
||||
|
</template> |
||||
|
{{ schema.labelMessage }} |
||||
|
</n-tooltip> |
||||
|
</template> |
||||
|
|
||||
|
<!--判断插槽--> |
||||
|
<template v-if="schema.slot"> |
||||
|
<slot |
||||
|
:name="schema.slot" |
||||
|
:model="formModel" |
||||
|
:field="schema.field" |
||||
|
:value="formModel[schema.field]" |
||||
|
></slot> |
||||
|
</template> |
||||
|
|
||||
|
<!--NCheckbox--> |
||||
|
<template v-else-if="schema.component === 'NCheckbox'"> |
||||
|
<n-checkbox-group v-model:value="formModel[schema.field]"> |
||||
|
<n-space> |
||||
|
<n-checkbox |
||||
|
v-for="item in schema.componentProps.options" |
||||
|
:key="item.value" |
||||
|
:value="item.value" |
||||
|
:label="item.label" |
||||
|
/> |
||||
|
</n-space> |
||||
|
</n-checkbox-group> |
||||
|
</template> |
||||
|
|
||||
|
<!--NRadioGroup--> |
||||
|
<template v-else-if="schema.component === 'NRadioGroup'"> |
||||
|
<n-radio-group v-model:value="formModel[schema.field]"> |
||||
|
<n-space> |
||||
|
<n-radio |
||||
|
v-for="item in schema.componentProps.options" |
||||
|
:key="item.value" |
||||
|
:value="item.value" |
||||
|
> |
||||
|
{{ item.label }} |
||||
|
</n-radio> |
||||
|
</n-space> |
||||
|
</n-radio-group> |
||||
|
</template> |
||||
|
<!--动态渲染表单组件--> |
||||
|
<component |
||||
|
v-else |
||||
|
v-bind="getComponentProps(schema)" |
||||
|
:is="schema.component" |
||||
|
v-model:value="formModel[schema.field]" |
||||
|
:class="{ isFull: schema.isFull != false && getProps.isFull }" |
||||
|
/> |
||||
|
<!--组件后面的内容--> |
||||
|
<template v-if="schema.suffix"> |
||||
|
<slot |
||||
|
:name="schema.suffix" |
||||
|
:model="formModel" |
||||
|
:field="schema.field" |
||||
|
:value="formModel[schema.field]" |
||||
|
></slot> |
||||
|
</template> |
||||
|
</n-form-item> |
||||
|
</n-gi> |
||||
|
<!--提交 重置 展开 收起 按钮--> |
||||
|
<n-gi |
||||
|
:span="isInline ? '' : 24" |
||||
|
:suffix="isInline ? true : false" |
||||
|
#="{ overflow }" |
||||
|
v-if="getProps.showActionButtonGroup" |
||||
|
> |
||||
|
<n-space |
||||
|
align="center" |
||||
|
:justify="isInline ? 'end' : 'start'" |
||||
|
:style="{ 'margin-left': `${isInline ? 12 : getProps.labelWidth}px` }" |
||||
|
> |
||||
|
<n-button |
||||
|
v-if="getProps.showSubmitButton" |
||||
|
v-bind="getSubmitBtnOptions" |
||||
|
@click="handleSubmit" |
||||
|
:loading="loadingSub" |
||||
|
>{{ getProps.submitButtonText }}</n-button |
||||
|
> |
||||
|
<n-button |
||||
|
v-if="getProps.showResetButton" |
||||
|
v-bind="getResetBtnOptions" |
||||
|
@click="resetFields" |
||||
|
>{{ getProps.resetButtonText }}</n-button |
||||
|
> |
||||
|
<n-button |
||||
|
type="primary" |
||||
|
text |
||||
|
icon-placement="right" |
||||
|
v-if="isInline && getProps.showAdvancedButton" |
||||
|
@click="unfoldToggle" |
||||
|
> |
||||
|
<template #icon> |
||||
|
<n-icon size="14" class="unfold-icon" v-if="overflow"> |
||||
|
<DownOutlined /> |
||||
|
</n-icon> |
||||
|
<n-icon size="14" class="unfold-icon" v-else> |
||||
|
<UpOutlined /> |
||||
|
</n-icon> |
||||
|
</template> |
||||
|
{{ overflow ? '展开' : '收起' }} |
||||
|
</n-button> |
||||
|
</n-space> |
||||
|
</n-gi> |
||||
|
</n-grid> |
||||
|
</n-form> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
import { defineComponent, reactive, ref, computed, unref, onMounted, watch } from 'vue'; |
||||
|
import { createPlaceholderMessage } from './helper'; |
||||
|
import { useFormEvents } from './hooks/useFormEvents'; |
||||
|
import { useFormValues } from './hooks/useFormValues'; |
||||
|
|
||||
|
import { basicProps } from './props'; |
||||
|
import { DownOutlined, UpOutlined, QuestionCircleOutlined } from '@vicons/antd'; |
||||
|
|
||||
|
import type { Ref } from 'vue'; |
||||
|
import type { GridProps } from 'naive-ui/lib/grid'; |
||||
|
import type { FormSchema, FormProps, FormActionType } from './types/form'; |
||||
|
|
||||
|
import { isArray } from '@/utils/is/index'; |
||||
|
import { deepMerge } from '@/utils'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
name: 'BasicForm', |
||||
|
components: { DownOutlined, UpOutlined, QuestionCircleOutlined }, |
||||
|
props: { |
||||
|
...basicProps, |
||||
|
}, |
||||
|
emits: ['reset', 'submit', 'register'], |
||||
|
setup(props, { emit, attrs }) { |
||||
|
const defaultFormModel = ref<Recordable>({}); |
||||
|
const formModel = reactive<Recordable>({}); |
||||
|
const propsRef = ref<Partial<FormProps>>({}); |
||||
|
const schemaRef = ref<Nullable<FormSchema[]>>(null); |
||||
|
const formElRef = ref<Nullable<FormActionType>>(null); |
||||
|
const gridCollapsed = ref(true); |
||||
|
const loadingSub = ref(false); |
||||
|
const isUpdateDefaultRef = ref(false); |
||||
|
|
||||
|
const getSubmitBtnOptions = computed(() => { |
||||
|
return Object.assign( |
||||
|
{ |
||||
|
size: props.size, |
||||
|
type: 'primary', |
||||
|
}, |
||||
|
props.submitButtonOptions |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
const getResetBtnOptions = computed(() => { |
||||
|
return Object.assign( |
||||
|
{ |
||||
|
size: props.size, |
||||
|
type: 'default', |
||||
|
}, |
||||
|
props.resetButtonOptions |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
function getComponentProps(schema) { |
||||
|
const compProps = schema.componentProps ?? {}; |
||||
|
const component = schema.component; |
||||
|
return { |
||||
|
clearable: true, |
||||
|
placeholder: createPlaceholderMessage(unref(component)), |
||||
|
...compProps, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
const getProps = computed((): FormProps => { |
||||
|
const formProps = { ...props, ...unref(propsRef) } as FormProps; |
||||
|
const rulesObj: any = { |
||||
|
rules: {}, |
||||
|
}; |
||||
|
const schemas: any = formProps.schemas || []; |
||||
|
schemas.forEach((item) => { |
||||
|
if (item.rules && isArray(item.rules)) { |
||||
|
rulesObj.rules[item.field] = item.rules; |
||||
|
} |
||||
|
}); |
||||
|
return { ...formProps, ...unref(rulesObj) }; |
||||
|
}); |
||||
|
|
||||
|
const isInline = computed(() => { |
||||
|
const { layout } = unref(getProps); |
||||
|
return layout === 'inline'; |
||||
|
}); |
||||
|
|
||||
|
const getGrid = computed((): GridProps => { |
||||
|
const { gridProps } = unref(getProps); |
||||
|
return { |
||||
|
...gridProps, |
||||
|
collapsed: isInline.value ? gridCollapsed.value : false, |
||||
|
responsive: 'screen', |
||||
|
}; |
||||
|
}); |
||||
|
|
||||
|
const getBindValue = computed( |
||||
|
() => ({ ...attrs, ...props, ...unref(getProps) } as Recordable) |
||||
|
); |
||||
|
|
||||
|
const getSchema = computed((): FormSchema[] => { |
||||
|
const schemas: FormSchema[] = unref(schemaRef) || (unref(getProps).schemas as any); |
||||
|
for (const schema of schemas) { |
||||
|
const { defaultValue } = schema; |
||||
|
// handle date type |
||||
|
// dateItemType.includes(component as string) |
||||
|
if (defaultValue) { |
||||
|
schema.defaultValue = defaultValue; |
||||
|
} |
||||
|
} |
||||
|
return schemas as FormSchema[]; |
||||
|
}); |
||||
|
|
||||
|
const { handleFormValues, initDefault } = useFormValues({ |
||||
|
defaultFormModel, |
||||
|
getSchema, |
||||
|
formModel, |
||||
|
}); |
||||
|
|
||||
|
const { handleSubmit, validate, resetFields, getFieldsValue, clearValidate, setFieldsValue } = |
||||
|
useFormEvents({ |
||||
|
emit, |
||||
|
getProps, |
||||
|
formModel, |
||||
|
getSchema, |
||||
|
formElRef: formElRef as Ref<FormActionType>, |
||||
|
defaultFormModel, |
||||
|
loadingSub, |
||||
|
handleFormValues, |
||||
|
}); |
||||
|
|
||||
|
function unfoldToggle() { |
||||
|
gridCollapsed.value = !gridCollapsed.value; |
||||
|
} |
||||
|
|
||||
|
async function setProps(formProps: Partial<FormProps>): Promise<void> { |
||||
|
propsRef.value = deepMerge(unref(propsRef) || {}, formProps); |
||||
|
} |
||||
|
|
||||
|
const formActionType: Partial<FormActionType> = { |
||||
|
getFieldsValue, |
||||
|
setFieldsValue, |
||||
|
resetFields, |
||||
|
validate, |
||||
|
clearValidate, |
||||
|
setProps, |
||||
|
submit: handleSubmit, |
||||
|
}; |
||||
|
|
||||
|
watch( |
||||
|
() => getSchema.value, |
||||
|
(schema) => { |
||||
|
if (unref(isUpdateDefaultRef)) { |
||||
|
return; |
||||
|
} |
||||
|
if (schema?.length) { |
||||
|
initDefault(); |
||||
|
isUpdateDefaultRef.value = true; |
||||
|
} |
||||
|
} |
||||
|
); |
||||
|
|
||||
|
onMounted(() => { |
||||
|
initDefault(); |
||||
|
emit('register', formActionType); |
||||
|
}); |
||||
|
|
||||
|
return { |
||||
|
formElRef, |
||||
|
formModel, |
||||
|
getGrid, |
||||
|
getProps, |
||||
|
getBindValue, |
||||
|
getSchema, |
||||
|
getSubmitBtnOptions, |
||||
|
getResetBtnOptions, |
||||
|
handleSubmit, |
||||
|
resetFields, |
||||
|
loadingSub, |
||||
|
isInline, |
||||
|
getComponentProps, |
||||
|
unfoldToggle, |
||||
|
}; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped> |
||||
|
.isFull { |
||||
|
width: 100%; |
||||
|
justify-content: flex-start; |
||||
|
} |
||||
|
|
||||
|
.unfold-icon { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
height: 100%; |
||||
|
margin-left: -3px; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,42 @@ |
|||||
|
import { ComponentType } from './types/index'; |
||||
|
|
||||
|
/** |
||||
|
* @description: 生成placeholder |
||||
|
*/ |
||||
|
export function createPlaceholderMessage(component: ComponentType) { |
||||
|
if (component === 'NInput') return '请输入'; |
||||
|
if ( |
||||
|
['NPicker', 'NSelect', 'NCheckbox', 'NRadio', 'NSwitch', 'NDatePicker', 'NTimePicker'].includes( |
||||
|
component |
||||
|
) |
||||
|
) |
||||
|
return '请选择'; |
||||
|
return ''; |
||||
|
} |
||||
|
|
||||
|
const DATE_TYPE = ['DatePicker', 'MonthPicker', 'WeekPicker', 'TimePicker']; |
||||
|
|
||||
|
function genType() { |
||||
|
return [...DATE_TYPE, 'RangePicker']; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 时间字段 |
||||
|
*/ |
||||
|
export const dateItemType = genType(); |
||||
|
|
||||
|
export function defaultType(component) { |
||||
|
if (component === 'NInput') return ''; |
||||
|
if (component === 'NInputNumber') return null; |
||||
|
return [ |
||||
|
'NPicker', |
||||
|
'NSelect', |
||||
|
'NCheckbox', |
||||
|
'NRadio', |
||||
|
'NSwitch', |
||||
|
'NDatePicker', |
||||
|
'NTimePicker', |
||||
|
].includes(component) |
||||
|
? '' |
||||
|
: undefined; |
||||
|
} |
@ -0,0 +1,86 @@ |
|||||
|
import type { FormProps, FormActionType, UseFormReturnType } from '../types/form'; |
||||
|
import type { DynamicProps } from '/#/utils'; |
||||
|
|
||||
|
import { ref, onUnmounted, unref, nextTick, watch } from 'vue'; |
||||
|
import { isProdMode } from '@/utils/env'; |
||||
|
import { getDynamicProps } from '@/utils'; |
||||
|
|
||||
|
type Props = Partial<DynamicProps<FormProps>>; |
||||
|
|
||||
|
export function useForm(props?: Props): UseFormReturnType { |
||||
|
const formRef = ref<Nullable<FormActionType>>(null); |
||||
|
const loadedRef = ref<Nullable<boolean>>(false); |
||||
|
|
||||
|
async function getForm() { |
||||
|
const form = unref(formRef); |
||||
|
if (!form) { |
||||
|
console.error( |
||||
|
'The form instance has not been obtained, please make sure that the form has been rendered when performing the form operation!' |
||||
|
); |
||||
|
} |
||||
|
await nextTick(); |
||||
|
return form as FormActionType; |
||||
|
} |
||||
|
|
||||
|
function register(instance: FormActionType) { |
||||
|
isProdMode() && |
||||
|
onUnmounted(() => { |
||||
|
formRef.value = null; |
||||
|
loadedRef.value = null; |
||||
|
}); |
||||
|
if (unref(loadedRef) && isProdMode() && instance === unref(formRef)) return; |
||||
|
|
||||
|
formRef.value = instance; |
||||
|
loadedRef.value = true; |
||||
|
|
||||
|
watch( |
||||
|
() => props, |
||||
|
() => { |
||||
|
props && instance.setProps(getDynamicProps(props)); |
||||
|
}, |
||||
|
{ |
||||
|
immediate: true, |
||||
|
deep: true, |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
const methods: FormActionType = { |
||||
|
setProps: async (formProps: Partial<FormProps>) => { |
||||
|
const form = await getForm(); |
||||
|
await form.setProps(formProps); |
||||
|
}, |
||||
|
|
||||
|
resetFields: async () => { |
||||
|
getForm().then(async (form) => { |
||||
|
await form.resetFields(); |
||||
|
}); |
||||
|
}, |
||||
|
|
||||
|
clearValidate: async (name?: string | string[]) => { |
||||
|
const form = await getForm(); |
||||
|
await form.clearValidate(name); |
||||
|
}, |
||||
|
|
||||
|
getFieldsValue: <T>() => { |
||||
|
return unref(formRef)?.getFieldsValue() as T; |
||||
|
}, |
||||
|
|
||||
|
setFieldsValue: async <T>(values: T) => { |
||||
|
const form = await getForm(); |
||||
|
await form.setFieldsValue<T>(values); |
||||
|
}, |
||||
|
|
||||
|
submit: async (): Promise<any> => { |
||||
|
const form = await getForm(); |
||||
|
return form.submit(); |
||||
|
}, |
||||
|
|
||||
|
validate: async (nameList?: any[]): Promise<Recordable> => { |
||||
|
const form = await getForm(); |
||||
|
return form.validate(nameList); |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
return [register, methods]; |
||||
|
} |
@ -0,0 +1,11 @@ |
|||||
|
import { provide, inject } from 'vue'; |
||||
|
|
||||
|
const key = Symbol('formElRef'); |
||||
|
|
||||
|
export function createFormContext(instance) { |
||||
|
provide(key, instance); |
||||
|
} |
||||
|
|
||||
|
export function useFormContext() { |
||||
|
return inject(key); |
||||
|
} |
@ -0,0 +1,107 @@ |
|||||
|
import type { ComputedRef, Ref } from 'vue'; |
||||
|
import type { FormProps, FormSchema, FormActionType } from '../types/form'; |
||||
|
import { unref, toRaw } from 'vue'; |
||||
|
import { isFunction } from '@/utils/is'; |
||||
|
|
||||
|
declare type EmitType = (event: string, ...args: any[]) => void; |
||||
|
|
||||
|
interface UseFormActionContext { |
||||
|
emit: EmitType; |
||||
|
getProps: ComputedRef<FormProps>; |
||||
|
getSchema: ComputedRef<FormSchema[]>; |
||||
|
formModel: Recordable; |
||||
|
formElRef: Ref<FormActionType>; |
||||
|
defaultFormModel: Recordable; |
||||
|
loadingSub: Ref<boolean>; |
||||
|
handleFormValues: Function; |
||||
|
} |
||||
|
|
||||
|
export function useFormEvents({ |
||||
|
emit, |
||||
|
getProps, |
||||
|
formModel, |
||||
|
getSchema, |
||||
|
formElRef, |
||||
|
defaultFormModel, |
||||
|
loadingSub, |
||||
|
handleFormValues, |
||||
|
}: UseFormActionContext) { |
||||
|
// 验证
|
||||
|
async function validate() { |
||||
|
return unref(formElRef)?.validate(); |
||||
|
} |
||||
|
|
||||
|
// 提交
|
||||
|
async function handleSubmit(e?: Event): Promise<void> { |
||||
|
e && e.preventDefault(); |
||||
|
loadingSub.value = true; |
||||
|
const { submitFunc } = unref(getProps); |
||||
|
if (submitFunc && isFunction(submitFunc)) { |
||||
|
await submitFunc(); |
||||
|
return; |
||||
|
} |
||||
|
const formEl = unref(formElRef); |
||||
|
if (!formEl) return; |
||||
|
try { |
||||
|
await validate(); |
||||
|
loadingSub.value = false; |
||||
|
emit('submit', formModel); |
||||
|
return; |
||||
|
} catch (error) { |
||||
|
loadingSub.value = false; |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//清空校验
|
||||
|
async function clearValidate() { |
||||
|
// @ts-ignore
|
||||
|
await unref(formElRef)?.restoreValidation(); |
||||
|
} |
||||
|
|
||||
|
//重置
|
||||
|
async function resetFields(): Promise<void> { |
||||
|
const { resetFunc, submitOnReset } = unref(getProps); |
||||
|
resetFunc && isFunction(resetFunc) && (await resetFunc()); |
||||
|
|
||||
|
const formEl = unref(formElRef); |
||||
|
if (!formEl) return; |
||||
|
Object.keys(formModel).forEach((key) => { |
||||
|
formModel[key] = unref(defaultFormModel)[key] || null; |
||||
|
}); |
||||
|
await clearValidate(); |
||||
|
const fromValues = handleFormValues(toRaw(unref(formModel))); |
||||
|
emit('reset', fromValues); |
||||
|
submitOnReset && (await handleSubmit()); |
||||
|
} |
||||
|
|
||||
|
//获取表单值
|
||||
|
function getFieldsValue(): Recordable { |
||||
|
const formEl = unref(formElRef); |
||||
|
if (!formEl) return {}; |
||||
|
return handleFormValues(toRaw(unref(formModel))); |
||||
|
} |
||||
|
|
||||
|
//设置表单字段值
|
||||
|
async function setFieldsValue(values: Recordable): Promise<void> { |
||||
|
const fields = unref(getSchema) |
||||
|
.map((item) => item.field) |
||||
|
.filter(Boolean); |
||||
|
|
||||
|
Object.keys(values).forEach((key) => { |
||||
|
const value = values[key]; |
||||
|
if (fields.includes(key)) { |
||||
|
formModel[key] = value; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
handleSubmit, |
||||
|
validate, |
||||
|
resetFields, |
||||
|
getFieldsValue, |
||||
|
clearValidate, |
||||
|
setFieldsValue, |
||||
|
}; |
||||
|
} |
@ -0,0 +1,54 @@ |
|||||
|
import { isArray, isFunction, isObject, isString, isNullOrUnDef } from '@/utils/is'; |
||||
|
import { unref } from 'vue'; |
||||
|
import type { Ref, ComputedRef } from 'vue'; |
||||
|
import type { FormSchema } from '../types/form'; |
||||
|
import { set } from 'lodash-es'; |
||||
|
|
||||
|
interface UseFormValuesContext { |
||||
|
defaultFormModel: Ref<any>; |
||||
|
getSchema: ComputedRef<FormSchema[]>; |
||||
|
formModel: Recordable; |
||||
|
} |
||||
|
export function useFormValues({ defaultFormModel, getSchema, formModel }: UseFormValuesContext) { |
||||
|
// 加工 form values
|
||||
|
function handleFormValues(values: Recordable) { |
||||
|
if (!isObject(values)) { |
||||
|
return {}; |
||||
|
} |
||||
|
const res: Recordable = {}; |
||||
|
for (const item of Object.entries(values)) { |
||||
|
let [, value] = item; |
||||
|
const [key] = item; |
||||
|
if ( |
||||
|
!key || |
||||
|
(isArray(value) && value.length === 0) || |
||||
|
isFunction(value) || |
||||
|
isNullOrUnDef(value) |
||||
|
) { |
||||
|
continue; |
||||
|
} |
||||
|
// 删除空格
|
||||
|
if (isString(value)) { |
||||
|
value = value.trim(); |
||||
|
} |
||||
|
set(res, key, value); |
||||
|
} |
||||
|
return res; |
||||
|
} |
||||
|
|
||||
|
//初始化默认值
|
||||
|
function initDefault() { |
||||
|
const schemas = unref(getSchema); |
||||
|
const obj: Recordable = {}; |
||||
|
schemas.forEach((item) => { |
||||
|
const { defaultValue } = item; |
||||
|
if (!isNullOrUnDef(defaultValue)) { |
||||
|
obj[item.field] = defaultValue; |
||||
|
formModel[item.field] = defaultValue; |
||||
|
} |
||||
|
}); |
||||
|
defaultFormModel.value = obj; |
||||
|
} |
||||
|
|
||||
|
return { handleFormValues, initDefault }; |
||||
|
} |
@ -0,0 +1,82 @@ |
|||||
|
import type { CSSProperties, PropType } from 'vue'; |
||||
|
import { FormSchema } from './types/form'; |
||||
|
import type { GridProps, GridItemProps } from 'naive-ui/lib/grid'; |
||||
|
import type { ButtonProps } from 'naive-ui/lib/button'; |
||||
|
import { propTypes } from '@/utils/propTypes'; |
||||
|
export const basicProps = { |
||||
|
// 标签宽度 固定宽度
|
||||
|
labelWidth: { |
||||
|
type: [Number, String] as PropType<number | string>, |
||||
|
default: 80, |
||||
|
}, |
||||
|
// 表单配置规则
|
||||
|
schemas: { |
||||
|
type: [Array] as PropType<FormSchema[]>, |
||||
|
default: () => [], |
||||
|
}, |
||||
|
//布局方式
|
||||
|
layout: { |
||||
|
type: String, |
||||
|
default: 'inline', |
||||
|
}, |
||||
|
//是否展示为行内表单
|
||||
|
inline: { |
||||
|
type: Boolean, |
||||
|
default: false, |
||||
|
}, |
||||
|
//大小
|
||||
|
size: { |
||||
|
type: String, |
||||
|
default: 'medium', |
||||
|
}, |
||||
|
//标签位置
|
||||
|
labelPlacement: { |
||||
|
type: String, |
||||
|
default: 'left', |
||||
|
}, |
||||
|
//组件是否width 100%
|
||||
|
isFull: { |
||||
|
type: Boolean, |
||||
|
default: true, |
||||
|
}, |
||||
|
//是否显示操作按钮(查询/重置)
|
||||
|
showActionButtonGroup: propTypes.bool.def(true), |
||||
|
// 显示重置按钮
|
||||
|
showResetButton: propTypes.bool.def(true), |
||||
|
//重置按钮配置
|
||||
|
resetButtonOptions: Object as PropType<Partial<ButtonProps>>, |
||||
|
// 显示确认按钮
|
||||
|
showSubmitButton: propTypes.bool.def(true), |
||||
|
// 确认按钮配置
|
||||
|
submitButtonOptions: Object as PropType<Partial<ButtonProps>>, |
||||
|
//展开收起按钮
|
||||
|
showAdvancedButton: propTypes.bool.def(true), |
||||
|
// 确认按钮文字
|
||||
|
submitButtonText: { |
||||
|
type: String, |
||||
|
default: '查询', |
||||
|
}, |
||||
|
//重置按钮文字
|
||||
|
resetButtonText: { |
||||
|
type: String, |
||||
|
default: '重置', |
||||
|
}, |
||||
|
//grid 配置
|
||||
|
gridProps: Object as PropType<GridProps>, |
||||
|
//gi配置
|
||||
|
giProps: Object as PropType<GridItemProps>, |
||||
|
//grid 样式
|
||||
|
baseGridStyle: { |
||||
|
type: Object as PropType<CSSProperties>, |
||||
|
}, |
||||
|
//是否折叠
|
||||
|
collapsed: { |
||||
|
type: Boolean, |
||||
|
default: false, |
||||
|
}, |
||||
|
//默认展示的行数
|
||||
|
collapsedRows: { |
||||
|
type: Number, |
||||
|
default: 1, |
||||
|
}, |
||||
|
}; |
@ -0,0 +1,59 @@ |
|||||
|
import { ComponentType } from './index'; |
||||
|
import type { CSSProperties } from 'vue'; |
||||
|
import type { GridProps, GridItemProps } from 'naive-ui/lib/grid'; |
||||
|
import type { ButtonProps } from 'naive-ui/lib/button'; |
||||
|
|
||||
|
export interface FormSchema { |
||||
|
field: string; |
||||
|
label: string; |
||||
|
labelMessage?: string; |
||||
|
labelMessageStyle?: object | string; |
||||
|
defaultValue?: any; |
||||
|
component?: ComponentType; |
||||
|
componentProps?: object; |
||||
|
slot?: string; |
||||
|
rules?: object | object[]; |
||||
|
giProps?: GridItemProps; |
||||
|
isFull?: boolean; |
||||
|
suffix?: string; |
||||
|
} |
||||
|
|
||||
|
export interface FormProps { |
||||
|
model?: Recordable; |
||||
|
labelWidth?: number | string; |
||||
|
schemas?: FormSchema[]; |
||||
|
inline: boolean; |
||||
|
layout?: string; |
||||
|
size: string; |
||||
|
labelPlacement: string; |
||||
|
isFull: boolean; |
||||
|
showActionButtonGroup?: boolean; |
||||
|
showResetButton?: boolean; |
||||
|
resetButtonOptions?: Partial<ButtonProps>; |
||||
|
showSubmitButton?: boolean; |
||||
|
showAdvancedButton?: boolean; |
||||
|
submitButtonOptions?: Partial<ButtonProps>; |
||||
|
submitButtonText?: string; |
||||
|
resetButtonText?: string; |
||||
|
gridProps?: GridProps; |
||||
|
giProps?: GridItemProps; |
||||
|
resetFunc?: () => Promise<void>; |
||||
|
submitFunc?: () => Promise<void>; |
||||
|
submitOnReset?: boolean; |
||||
|
baseGridStyle?: CSSProperties; |
||||
|
collapsedRows?: number; |
||||
|
} |
||||
|
|
||||
|
export interface FormActionType { |
||||
|
submit: () => Promise<any>; |
||||
|
setProps: (formProps: Partial<FormProps>) => Promise<void>; |
||||
|
setFieldsValue: (values: Recordable) => Promise<void>; |
||||
|
clearValidate: (name?: string | string[]) => Promise<void>; |
||||
|
getFieldsValue: () => Recordable; |
||||
|
resetFields: () => Promise<void>; |
||||
|
validate: (nameList?: any[]) => Promise<any>; |
||||
|
} |
||||
|
|
||||
|
export type RegisterFn = (formInstance: FormActionType) => void; |
||||
|
|
||||
|
export type UseFormReturnType = [RegisterFn, FormActionType]; |
@ -0,0 +1,28 @@ |
|||||
|
export type ComponentType = |
||||
|
| 'NInput' |
||||
|
| 'NInputGroup' |
||||
|
| 'NInputPassword' |
||||
|
| 'NInputSearch' |
||||
|
| 'NInputTextArea' |
||||
|
| 'NInputNumber' |
||||
|
| 'NInputCountDown' |
||||
|
| 'NSelect' |
||||
|
| 'NTreeSelect' |
||||
|
| 'NRadioButtonGroup' |
||||
|
| 'NRadioGroup' |
||||
|
| 'NCheckbox' |
||||
|
| 'NCheckboxGroup' |
||||
|
| 'NAutoComplete' |
||||
|
| 'NCascader' |
||||
|
| 'NDatePicker' |
||||
|
| 'NMonthPicker' |
||||
|
| 'NRangePicker' |
||||
|
| 'NWeekPicker' |
||||
|
| 'NTimePicker' |
||||
|
| 'NSwitch' |
||||
|
| 'NStrengthMeter' |
||||
|
| 'NUpload' |
||||
|
| 'NIconPicker' |
||||
|
| 'NRender' |
||||
|
| 'NSlider' |
||||
|
| 'NRate'; |
@ -0,0 +1,304 @@ |
|||||
|
<template> |
||||
|
<div |
||||
|
:class="{ onLockLogin: showLogin }" |
||||
|
class="lockscreen" |
||||
|
@keyup="onLockLogin(true)" |
||||
|
@mousedown.stop |
||||
|
@contextmenu.prevent |
||||
|
> |
||||
|
<template v-if="!showLogin"> |
||||
|
<div class="lock-box"> |
||||
|
<div class="lock"> |
||||
|
<span class="lock-icon" title="解锁屏幕" @click="onLockLogin(true)"> |
||||
|
<n-icon> |
||||
|
<lock-outlined /> |
||||
|
</n-icon> |
||||
|
</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<!--充电--> |
||||
|
<recharge |
||||
|
:battery="battery" |
||||
|
:battery-status="batteryStatus" |
||||
|
:calc-discharging-time="calcDischargingTime" |
||||
|
:calc-charging-time="calcChargingTime" |
||||
|
/> |
||||
|
|
||||
|
<div class="local-time"> |
||||
|
<div class="time">{{ hour }}:{{ minute }}</div> |
||||
|
<div class="date">{{ month }}月{{ day }}号,星期{{ week }}</div> |
||||
|
</div> |
||||
|
<div class="computer-status"> |
||||
|
<span :class="{ offline: !online }" class="network"> |
||||
|
<wifi-outlined class="network" /> |
||||
|
</span> |
||||
|
<api-outlined /> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<!--登录--> |
||||
|
<template v-if="showLogin"> |
||||
|
<div class="login-box"> |
||||
|
<n-avatar :size="128"> |
||||
|
<n-icon> |
||||
|
<user-outlined /> |
||||
|
</n-icon> |
||||
|
</n-avatar> |
||||
|
<div class="username">{{ loginParams.username }}</div> |
||||
|
<n-input |
||||
|
type="password" |
||||
|
autofocus |
||||
|
v-model:value="loginParams.password" |
||||
|
@keyup.enter="onLogin" |
||||
|
placeholder="请输入登录密码" |
||||
|
> |
||||
|
<template #suffix> |
||||
|
<n-icon @click="onLogin" style="cursor: pointer"> |
||||
|
<LoadingOutlined v-if="loginLoading" /> |
||||
|
<arrow-right-outlined v-else /> |
||||
|
</n-icon> |
||||
|
</template> |
||||
|
</n-input> |
||||
|
|
||||
|
<div class="flex w-full" v-if="isLoginError"> |
||||
|
<span class="text-red-500">{{ errorMsg }}</span> |
||||
|
</div> |
||||
|
|
||||
|
<div class="flex justify-around w-full mt-1"> |
||||
|
<div><a @click="showLogin = false">返回</a></div> |
||||
|
<div><a @click="goLogin">重新登录</a></div> |
||||
|
<div><a @click="onLogin">进入系统</a></div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
import { defineComponent, reactive, toRefs } from 'vue'; |
||||
|
import { ResultEnum } from '@/enums/httpEnum'; |
||||
|
import recharge from './Recharge.vue'; |
||||
|
import { |
||||
|
LockOutlined, |
||||
|
LoadingOutlined, |
||||
|
UserOutlined, |
||||
|
ApiOutlined, |
||||
|
ArrowRightOutlined, |
||||
|
WifiOutlined, |
||||
|
} from '@vicons/antd'; |
||||
|
|
||||
|
import { useRouter, useRoute } from 'vue-router'; |
||||
|
import { useOnline } from '@/hooks/useOnline'; |
||||
|
import { useTime } from '@/hooks/useTime'; |
||||
|
import { useBattery } from '@/hooks/useBattery'; |
||||
|
import { useScreenLockStore } from '@/store/modules/screenLock'; |
||||
|
import { UserInfoType, useUserStore } from '@/store/modules/user'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
name: 'ScreenLock', |
||||
|
components: { |
||||
|
LockOutlined, |
||||
|
LoadingOutlined, |
||||
|
UserOutlined, |
||||
|
ArrowRightOutlined, |
||||
|
ApiOutlined, |
||||
|
WifiOutlined, |
||||
|
recharge, |
||||
|
}, |
||||
|
setup() { |
||||
|
const useScreenLock = useScreenLockStore(); |
||||
|
const userStore = useUserStore(); |
||||
|
|
||||
|
// 获取时间 |
||||
|
const { month, day, hour, minute, second, week } = useTime(); |
||||
|
const { online } = useOnline(); |
||||
|
|
||||
|
const router = useRouter(); |
||||
|
const route = useRoute(); |
||||
|
|
||||
|
const { battery, batteryStatus, calcDischargingTime, calcChargingTime } = useBattery(); |
||||
|
const userInfo: UserInfoType = userStore.getUserInfo || {}; |
||||
|
const username = userInfo['username'] || ''; |
||||
|
const state = reactive({ |
||||
|
showLogin: false, |
||||
|
loginLoading: false, // 正在登录 |
||||
|
isLoginError: false, //密码错误 |
||||
|
errorMsg: '密码错误', |
||||
|
loginParams: { |
||||
|
username: username || '', |
||||
|
password: '', |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
// 解锁登录 |
||||
|
const onLockLogin = (value: boolean) => (state.showLogin = value); |
||||
|
|
||||
|
// 登录 |
||||
|
const onLogin = async () => { |
||||
|
if (!state.loginParams.password.trim()) { |
||||
|
return; |
||||
|
} |
||||
|
const params = { |
||||
|
isLock: true, |
||||
|
...state.loginParams, |
||||
|
}; |
||||
|
state.loginLoading = true; |
||||
|
const { code, message } = await userStore.login(params); |
||||
|
if (code === ResultEnum.SUCCESS) { |
||||
|
onLockLogin(false); |
||||
|
useScreenLock.setLock(false); |
||||
|
} else { |
||||
|
state.errorMsg = message; |
||||
|
state.isLoginError = true; |
||||
|
} |
||||
|
state.loginLoading = false; |
||||
|
}; |
||||
|
|
||||
|
//重新登录 |
||||
|
const goLogin = () => { |
||||
|
onLockLogin(false); |
||||
|
useScreenLock.setLock(false); |
||||
|
router.replace({ |
||||
|
path: '/login', |
||||
|
query: { |
||||
|
redirect: route.fullPath, |
||||
|
}, |
||||
|
}); |
||||
|
}; |
||||
|
|
||||
|
return { |
||||
|
...toRefs(state), |
||||
|
online, |
||||
|
month, |
||||
|
day, |
||||
|
hour, |
||||
|
minute, |
||||
|
second, |
||||
|
week, |
||||
|
battery, |
||||
|
batteryStatus, |
||||
|
calcDischargingTime, |
||||
|
calcChargingTime, |
||||
|
onLockLogin, |
||||
|
onLogin, |
||||
|
goLogin, |
||||
|
}; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped> |
||||
|
.lockscreen { |
||||
|
position: fixed; |
||||
|
top: 0; |
||||
|
left: 0; |
||||
|
bottom: 0; |
||||
|
right: 0; |
||||
|
display: flex; |
||||
|
background: #000; |
||||
|
color: white; |
||||
|
overflow: hidden; |
||||
|
z-index: 9999; |
||||
|
|
||||
|
&.onLockLogin { |
||||
|
background-color: rgba(25, 28, 34, 0.88); |
||||
|
backdrop-filter: blur(7px); |
||||
|
} |
||||
|
|
||||
|
.login-box { |
||||
|
position: absolute; |
||||
|
top: 45%; |
||||
|
left: 50%; |
||||
|
transform: translate(-50%, -50%); |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
justify-content: center; |
||||
|
align-items: center; |
||||
|
|
||||
|
> * { |
||||
|
margin-bottom: 14px; |
||||
|
} |
||||
|
|
||||
|
.username { |
||||
|
font-size: 30px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.lock-box { |
||||
|
position: absolute; |
||||
|
top: 20px; |
||||
|
left: 50%; |
||||
|
transform: translateX(-50%); |
||||
|
font-size: 34px; |
||||
|
z-index: 100; |
||||
|
|
||||
|
.tips { |
||||
|
color: white; |
||||
|
cursor: text; |
||||
|
} |
||||
|
|
||||
|
.lock { |
||||
|
display: flex; |
||||
|
justify-content: center; |
||||
|
|
||||
|
.lock-icon { |
||||
|
cursor: pointer; |
||||
|
|
||||
|
.anticon-unlock { |
||||
|
display: none; |
||||
|
} |
||||
|
|
||||
|
&:hover .anticon-unlock { |
||||
|
display: initial; |
||||
|
} |
||||
|
|
||||
|
&:hover .anticon-lock { |
||||
|
display: none; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.local-time { |
||||
|
position: absolute; |
||||
|
bottom: 60px; |
||||
|
left: 60px; |
||||
|
font-family: helvetica; |
||||
|
|
||||
|
.time { |
||||
|
font-size: 70px; |
||||
|
} |
||||
|
|
||||
|
.date { |
||||
|
font-size: 40px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.computer-status { |
||||
|
position: absolute; |
||||
|
bottom: 60px; |
||||
|
right: 60px; |
||||
|
font-size: 24px; |
||||
|
|
||||
|
> * { |
||||
|
margin-left: 14px; |
||||
|
} |
||||
|
|
||||
|
.network { |
||||
|
position: relative; |
||||
|
|
||||
|
&.offline::before { |
||||
|
content: ''; |
||||
|
position: absolute; |
||||
|
left: 50%; |
||||
|
top: 50%; |
||||
|
width: 2px; |
||||
|
height: 28px; |
||||
|
transform: translate(-50%, -50%) rotate(45deg); |
||||
|
background-color: red; |
||||
|
z-index: 10; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,164 @@ |
|||||
|
<template> |
||||
|
<div class="container"> |
||||
|
<div class="number">{{ battery.level }}%</div> |
||||
|
<div class="contrast"> |
||||
|
<div class="circle"></div> |
||||
|
<ul class="bubbles"> |
||||
|
<li v-for="i in 15" :key="i"></li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
<div class="charging"> |
||||
|
<div>{{ batteryStatus }}</div> |
||||
|
<div v-show="Number.isFinite(battery.dischargingTime) && battery.dischargingTime != 0"> |
||||
|
剩余可使用时间:{{ calcDischargingTime }} |
||||
|
</div> |
||||
|
<span v-show="Number.isFinite(battery.chargingTime) && battery.chargingTime != 0"> |
||||
|
距离电池充满需要:{{ calcChargingTime }} |
||||
|
</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
import { defineComponent } from 'vue'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
name: 'HuaweiCharge', |
||||
|
// props: ['batteryStatus', 'battery', 'calcDischargingTime'], |
||||
|
props: { |
||||
|
battery: { |
||||
|
// 电池对象 |
||||
|
type: Object, |
||||
|
default: () => ({}), |
||||
|
}, |
||||
|
calcDischargingTime: { |
||||
|
// 电池剩余时间可用时间 |
||||
|
type: String, |
||||
|
default: '', |
||||
|
}, |
||||
|
calcChargingTime: { |
||||
|
type: String, |
||||
|
default: '', |
||||
|
}, |
||||
|
batteryStatus: { |
||||
|
// 电池状态 |
||||
|
type: String, |
||||
|
validator: (val: string) => ['充电中', '已充满', '已断开电源'].includes(val), |
||||
|
}, |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less" scoped> |
||||
|
.container { |
||||
|
position: absolute; |
||||
|
bottom: 20vh; |
||||
|
left: 50vw; |
||||
|
width: 300px; |
||||
|
height: 500px; |
||||
|
transform: translateX(-50%); |
||||
|
|
||||
|
.number { |
||||
|
position: absolute; |
||||
|
top: 20%; |
||||
|
z-index: 10; |
||||
|
width: 300px; |
||||
|
font-size: 32px; |
||||
|
color: #fff; |
||||
|
text-align: center; |
||||
|
} |
||||
|
|
||||
|
.contrast { |
||||
|
width: 300px; |
||||
|
height: 400px; |
||||
|
overflow: hidden; |
||||
|
background-color: #000; |
||||
|
filter: contrast(15) hue-rotate(0); |
||||
|
animation: hueRotate 10s infinite linear; |
||||
|
|
||||
|
.circle { |
||||
|
position: relative; |
||||
|
width: 300px; |
||||
|
height: 300px; |
||||
|
filter: blur(8px); |
||||
|
box-sizing: border-box; |
||||
|
|
||||
|
&::after { |
||||
|
position: absolute; |
||||
|
top: 40%; |
||||
|
left: 50%; |
||||
|
width: 200px; |
||||
|
height: 200px; |
||||
|
background-color: #00ff6f; |
||||
|
border-radius: 42% 38% 62% 49% / 45%; |
||||
|
content: ''; |
||||
|
transform: translate(-50%, -50%) rotate(0); |
||||
|
animation: rotate 10s infinite linear; |
||||
|
} |
||||
|
|
||||
|
&::before { |
||||
|
position: absolute; |
||||
|
top: 40%; |
||||
|
left: 50%; |
||||
|
z-index: 10; |
||||
|
width: 176px; |
||||
|
height: 176px; |
||||
|
background-color: #000; |
||||
|
border-radius: 50%; |
||||
|
content: ''; |
||||
|
transform: translate(-50%, -50%); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.bubbles { |
||||
|
position: absolute; |
||||
|
bottom: 0; |
||||
|
left: 50%; |
||||
|
width: 100px; |
||||
|
height: 40px; |
||||
|
background-color: #00ff6f; |
||||
|
border-radius: 100px 100px 0 0; |
||||
|
filter: blur(5px); |
||||
|
transform: translate(-50%, 0); |
||||
|
|
||||
|
li { |
||||
|
position: absolute; |
||||
|
background: #00ff6f; |
||||
|
border-radius: 50%; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.charging { |
||||
|
font-size: 20px; |
||||
|
text-align: center; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes rotate { |
||||
|
50% { |
||||
|
border-radius: 45% / 42% 38% 58% 49%; |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
transform: translate(-50%, -50%) rotate(720deg); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes moveToTop { |
||||
|
90% { |
||||
|
opacity: 1; |
||||
|
} |
||||
|
|
||||
|
100% { |
||||
|
opacity: 0.1; |
||||
|
transform: translate(-50%, -180px); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@keyframes hueRotate { |
||||
|
100% { |
||||
|
filter: contrast(15) hue-rotate(360deg); |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,3 @@ |
|||||
|
import LockScreen from './Lockscreen.vue'; |
||||
|
|
||||
|
export { LockScreen }; |
@ -0,0 +1,3 @@ |
|||||
|
export { default as basicModal } from './src/basicModal.vue'; |
||||
|
export { useModal } from './src/hooks/useModal'; |
||||
|
export * from './src/type'; |
@ -0,0 +1,117 @@ |
|||||
|
<template> |
||||
|
<n-modal id="basic-modal" v-bind="getBindValue" v-model:show="isModal" @close="onCloseModal"> |
||||
|
<template #header> |
||||
|
<div class="w-full cursor-move" id="basic-modal-bar">{{ getBindValue.title }}</div> |
||||
|
</template> |
||||
|
<template #default> |
||||
|
<slot name="default"></slot> |
||||
|
</template> |
||||
|
<template #action v-if="!$slots.action"> |
||||
|
<n-space> |
||||
|
<n-button @click="closeModal">取消</n-button> |
||||
|
<n-button type="primary" :loading="subLoading" @click="handleSubmit">{{ |
||||
|
subBtuText |
||||
|
}}</n-button> |
||||
|
</n-space> |
||||
|
</template> |
||||
|
<template v-else #action> |
||||
|
<slot name="action"></slot> |
||||
|
</template> |
||||
|
</n-modal> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts" setup> |
||||
|
import { |
||||
|
getCurrentInstance, |
||||
|
ref, |
||||
|
nextTick, |
||||
|
unref, |
||||
|
computed, |
||||
|
useAttrs, |
||||
|
defineEmits, |
||||
|
defineProps, |
||||
|
} from 'vue'; |
||||
|
import { basicProps } from './props'; |
||||
|
import startDrag from '@/utils/Drag'; |
||||
|
import { deepMerge } from '@/utils'; |
||||
|
import { FormProps } from '@/components/Form'; |
||||
|
import { ModalProps, ModalMethods } from './type'; |
||||
|
|
||||
|
const attrs = useAttrs(); |
||||
|
const props = defineProps({ ...basicProps }); |
||||
|
const emit = defineEmits(['on-close', 'on-ok', 'register']); |
||||
|
|
||||
|
const propsRef = ref<Partial<ModalProps> | null>(null); |
||||
|
|
||||
|
const isModal = ref(false); |
||||
|
const subLoading = ref(false); |
||||
|
|
||||
|
const getProps = computed((): FormProps => { |
||||
|
return { ...props, ...(unref(propsRef) as any) }; |
||||
|
}); |
||||
|
|
||||
|
const subBtuText = computed(() => { |
||||
|
const { subBtuText } = propsRef.value as any; |
||||
|
return subBtuText || props.subBtuText; |
||||
|
}); |
||||
|
|
||||
|
async function setProps(modalProps: Partial<ModalProps>): Promise<void> { |
||||
|
propsRef.value = deepMerge(unref(propsRef) || ({} as any), modalProps); |
||||
|
} |
||||
|
|
||||
|
const getBindValue = computed(() => { |
||||
|
return { |
||||
|
...attrs, |
||||
|
...unref(getProps), |
||||
|
...unref(propsRef), |
||||
|
}; |
||||
|
}); |
||||
|
|
||||
|
function setSubLoading(status: boolean) { |
||||
|
subLoading.value = status; |
||||
|
} |
||||
|
|
||||
|
function openModal() { |
||||
|
isModal.value = true; |
||||
|
nextTick(() => { |
||||
|
const oBox = document.getElementById('basic-modal'); |
||||
|
const oBar = document.getElementById('basic-modal-bar'); |
||||
|
startDrag(oBar, oBox); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function closeModal() { |
||||
|
isModal.value = false; |
||||
|
subLoading.value = false; |
||||
|
emit('on-close'); |
||||
|
} |
||||
|
|
||||
|
function onCloseModal() { |
||||
|
isModal.value = false; |
||||
|
emit('on-close'); |
||||
|
} |
||||
|
|
||||
|
function handleSubmit() { |
||||
|
subLoading.value = true; |
||||
|
console.log(subLoading.value); |
||||
|
emit('on-ok'); |
||||
|
} |
||||
|
|
||||
|
const modalMethods: ModalMethods = { |
||||
|
setProps, |
||||
|
openModal, |
||||
|
closeModal, |
||||
|
setSubLoading, |
||||
|
}; |
||||
|
|
||||
|
const instance = getCurrentInstance(); |
||||
|
if (instance) { |
||||
|
emit('register', modalMethods); |
||||
|
} |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less"> |
||||
|
.cursor-move { |
||||
|
cursor: move; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,54 @@ |
|||||
|
import { ref, unref, getCurrentInstance, watch } from 'vue'; |
||||
|
import { isProdMode } from '@/utils/env'; |
||||
|
import { ModalMethods, UseModalReturnType } from '../type'; |
||||
|
import { getDynamicProps } from '@/utils'; |
||||
|
import { tryOnUnmounted } from '@vueuse/core'; |
||||
|
export function useModal(props): UseModalReturnType { |
||||
|
const modalRef = ref<Nullable<ModalMethods>>(null); |
||||
|
const currentInstance = getCurrentInstance(); |
||||
|
|
||||
|
const getInstance = () => { |
||||
|
const instance = unref(modalRef.value); |
||||
|
if (!instance) { |
||||
|
console.error('useModal instance is undefined!'); |
||||
|
} |
||||
|
return instance; |
||||
|
}; |
||||
|
|
||||
|
const register = (modalInstance: ModalMethods) => { |
||||
|
isProdMode() && |
||||
|
tryOnUnmounted(() => { |
||||
|
modalRef.value = null; |
||||
|
}); |
||||
|
modalRef.value = modalInstance; |
||||
|
currentInstance?.emit('register', modalInstance); |
||||
|
|
||||
|
watch( |
||||
|
() => props, |
||||
|
() => { |
||||
|
props && modalInstance.setProps(getDynamicProps(props)); |
||||
|
}, |
||||
|
{ |
||||
|
immediate: true, |
||||
|
deep: true, |
||||
|
} |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
const methods: ModalMethods = { |
||||
|
setProps: (props): void => { |
||||
|
getInstance()?.setProps(props); |
||||
|
}, |
||||
|
openModal: () => { |
||||
|
getInstance()?.openModal(); |
||||
|
}, |
||||
|
closeModal: () => { |
||||
|
getInstance()?.closeModal(); |
||||
|
}, |
||||
|
setSubLoading: (status) => { |
||||
|
getInstance()?.setSubLoading(status); |
||||
|
}, |
||||
|
}; |
||||
|
|
||||
|
return [register, methods]; |
||||
|
} |
@ -0,0 +1,30 @@ |
|||||
|
import { NModal } from 'naive-ui'; |
||||
|
|
||||
|
export const basicProps = { |
||||
|
...NModal.props, |
||||
|
// 确认按钮文字
|
||||
|
subBtuText: { |
||||
|
type: String, |
||||
|
default: '确认', |
||||
|
}, |
||||
|
showIcon: { |
||||
|
type: Boolean, |
||||
|
default: false, |
||||
|
}, |
||||
|
width: { |
||||
|
type: Number, |
||||
|
default: 446, |
||||
|
}, |
||||
|
title: { |
||||
|
type: String, |
||||
|
default: '', |
||||
|
}, |
||||
|
maskClosable: { |
||||
|
type: Boolean, |
||||
|
default: false, |
||||
|
}, |
||||
|
preset: { |
||||
|
type: String, |
||||
|
default: 'dialog', |
||||
|
}, |
||||
|
}; |
@ -0,0 +1,19 @@ |
|||||
|
import type { DialogOptions } from 'naive-ui/lib/dialog'; |
||||
|
/** |
||||
|
* @description: 弹窗对外暴露的方法 |
||||
|
*/ |
||||
|
export interface ModalMethods { |
||||
|
setProps: (props) => void; |
||||
|
openModal: () => void; |
||||
|
closeModal: () => void; |
||||
|
setSubLoading: (status) => void; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 支持修改,DialogOptions 參數 |
||||
|
*/ |
||||
|
export type ModalProps = DialogOptions; |
||||
|
|
||||
|
export type RegisterFn = (ModalInstance: ModalMethods) => void; |
||||
|
|
||||
|
export type UseModalReturnType = [RegisterFn, ModalMethods]; |
@ -0,0 +1,4 @@ |
|||||
|
export { default as BasicTable } from './src/Table.vue'; |
||||
|
export { default as TableAction } from './src/components/TableAction.vue'; |
||||
|
export * from './src/types/table'; |
||||
|
export * from './src/types/tableAction'; |
@ -0,0 +1,353 @@ |
|||||
|
<template> |
||||
|
<div class="table-toolbar"> |
||||
|
<!--顶部左侧区域--> |
||||
|
<div class="flex items-center table-toolbar-left"> |
||||
|
<template v-if="title"> |
||||
|
<div class="table-toolbar-left-title"> |
||||
|
{{ title }} |
||||
|
<n-tooltip trigger="hover" v-if="titleTooltip"> |
||||
|
<template #trigger> |
||||
|
<n-icon size="18" class="ml-1 text-gray-400 cursor-pointer"> |
||||
|
<QuestionCircleOutlined /> |
||||
|
</n-icon> |
||||
|
</template> |
||||
|
{{ titleTooltip }} |
||||
|
</n-tooltip> |
||||
|
</div> |
||||
|
</template> |
||||
|
<slot name="tableTitle"></slot> |
||||
|
</div> |
||||
|
|
||||
|
<div class="flex items-center table-toolbar-right"> |
||||
|
<!--顶部右侧区域--> |
||||
|
<slot name="toolbar"></slot> |
||||
|
|
||||
|
<!--斑马纹--> |
||||
|
<n-tooltip trigger="hover"> |
||||
|
<template #trigger> |
||||
|
<div class="mr-2 table-toolbar-right-icon"> |
||||
|
<n-switch v-model:value="isStriped" @update:value="setStriped" /> |
||||
|
</div> |
||||
|
</template> |
||||
|
<span>表格斑马纹</span> |
||||
|
</n-tooltip> |
||||
|
<n-divider vertical /> |
||||
|
|
||||
|
<!--刷新--> |
||||
|
<n-tooltip trigger="hover"> |
||||
|
<template #trigger> |
||||
|
<div class="table-toolbar-right-icon" @click="reload"> |
||||
|
<n-icon size="18"> |
||||
|
<ReloadOutlined /> |
||||
|
</n-icon> |
||||
|
</div> |
||||
|
</template> |
||||
|
<span>刷新</span> |
||||
|
</n-tooltip> |
||||
|
|
||||
|
<!--密度--> |
||||
|
<n-tooltip trigger="hover"> |
||||
|
<template #trigger> |
||||
|
<div class="table-toolbar-right-icon"> |
||||
|
<n-dropdown |
||||
|
@select="densitySelect" |
||||
|
trigger="click" |
||||
|
:options="densityOptions" |
||||
|
v-model:value="tableSize" |
||||
|
> |
||||
|
<n-icon size="18"> |
||||
|
<ColumnHeightOutlined /> |
||||
|
</n-icon> |
||||
|
</n-dropdown> |
||||
|
</div> |
||||
|
</template> |
||||
|
<span>密度</span> |
||||
|
</n-tooltip> |
||||
|
|
||||
|
<!--表格设置单独抽离成组件--> |
||||
|
<ColumnSetting /> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="s-table"> |
||||
|
<n-data-table |
||||
|
ref="tableElRef" |
||||
|
v-bind="getBindValues" |
||||
|
:striped="isStriped" |
||||
|
:pagination="pagination" |
||||
|
@update:page="updatePage" |
||||
|
@update:page-size="updatePageSize" |
||||
|
> |
||||
|
<template #[item]="data" v-for="item in Object.keys($slots)" :key="item"> |
||||
|
<slot :name="item" v-bind="data"></slot> |
||||
|
</template> |
||||
|
</n-data-table> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
import { |
||||
|
ref, |
||||
|
defineComponent, |
||||
|
reactive, |
||||
|
unref, |
||||
|
toRaw, |
||||
|
computed, |
||||
|
toRefs, |
||||
|
onMounted, |
||||
|
nextTick, |
||||
|
} from 'vue'; |
||||
|
import { ReloadOutlined, ColumnHeightOutlined, QuestionCircleOutlined } from '@vicons/antd'; |
||||
|
import { createTableContext } from './hooks/useTableContext'; |
||||
|
|
||||
|
import ColumnSetting from './components/settings/ColumnSetting.vue'; |
||||
|
|
||||
|
import { useLoading } from './hooks/useLoading'; |
||||
|
import { useColumns } from './hooks/useColumns'; |
||||
|
import { useDataSource } from './hooks/useDataSource'; |
||||
|
import { usePagination } from './hooks/usePagination'; |
||||
|
|
||||
|
import { basicProps } from './props'; |
||||
|
|
||||
|
import { BasicTableProps } from './types/table'; |
||||
|
|
||||
|
import { getViewportOffset } from '@/utils/domUtils'; |
||||
|
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn'; |
||||
|
import { isBoolean } from '@/utils/is'; |
||||
|
|
||||
|
const densityOptions = [ |
||||
|
{ |
||||
|
type: 'menu', |
||||
|
label: '紧凑', |
||||
|
key: 'small', |
||||
|
}, |
||||
|
{ |
||||
|
type: 'menu', |
||||
|
label: '默认', |
||||
|
key: 'medium', |
||||
|
}, |
||||
|
{ |
||||
|
type: 'menu', |
||||
|
label: '宽松', |
||||
|
key: 'large', |
||||
|
}, |
||||
|
]; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
components: { |
||||
|
ReloadOutlined, |
||||
|
ColumnHeightOutlined, |
||||
|
ColumnSetting, |
||||
|
QuestionCircleOutlined, |
||||
|
}, |
||||
|
props: { |
||||
|
...basicProps, |
||||
|
}, |
||||
|
emits: [ |
||||
|
'fetch-success', |
||||
|
'fetch-error', |
||||
|
'update:checked-row-keys', |
||||
|
'edit-end', |
||||
|
'edit-cancel', |
||||
|
'edit-row-end', |
||||
|
'edit-change', |
||||
|
], |
||||
|
setup(props, { emit }) { |
||||
|
const deviceHeight = ref(150); |
||||
|
const tableElRef = ref<ComponentRef>(null); |
||||
|
const wrapRef = ref<Nullable<HTMLDivElement>>(null); |
||||
|
let paginationEl: HTMLElement | null; |
||||
|
const isStriped = ref(false); |
||||
|
const tableData = ref<Recordable[]>([]); |
||||
|
const innerPropsRef = ref<Partial<BasicTableProps>>(); |
||||
|
|
||||
|
const getProps = computed(() => { |
||||
|
return { ...props, ...unref(innerPropsRef) } as BasicTableProps; |
||||
|
}); |
||||
|
|
||||
|
const { getLoading, setLoading } = useLoading(getProps); |
||||
|
|
||||
|
const { getPaginationInfo, setPagination } = usePagination(getProps); |
||||
|
|
||||
|
const { getDataSourceRef, getDataSource, getRowKey, reload } = useDataSource( |
||||
|
getProps, |
||||
|
{ |
||||
|
getPaginationInfo, |
||||
|
setPagination, |
||||
|
tableData, |
||||
|
setLoading, |
||||
|
}, |
||||
|
emit |
||||
|
); |
||||
|
|
||||
|
const { getPageColumns, setColumns, getColumns, getCacheColumns, setCacheColumnsField } = |
||||
|
useColumns(getProps); |
||||
|
|
||||
|
const state = reactive({ |
||||
|
tableSize: unref(getProps as any).size || 'medium', |
||||
|
isColumnSetting: false, |
||||
|
}); |
||||
|
|
||||
|
//页码切换 |
||||
|
function updatePage(page) { |
||||
|
setPagination({ page: page }); |
||||
|
reload(); |
||||
|
} |
||||
|
|
||||
|
//分页数量切换 |
||||
|
function updatePageSize(size) { |
||||
|
setPagination({ page: 1, pageSize: size }); |
||||
|
reload(); |
||||
|
} |
||||
|
|
||||
|
//密度切换 |
||||
|
function densitySelect(e) { |
||||
|
state.tableSize = e; |
||||
|
} |
||||
|
|
||||
|
//选中行 |
||||
|
function updateCheckedRowKeys(rowKeys) { |
||||
|
emit('update:checked-row-keys', rowKeys); |
||||
|
} |
||||
|
|
||||
|
//获取表格大小 |
||||
|
const getTableSize = computed(() => state.tableSize); |
||||
|
|
||||
|
//组装表格信息 |
||||
|
const getBindValues = computed(() => { |
||||
|
const tableData = unref(getDataSourceRef); |
||||
|
const maxHeight = tableData.length ? `${unref(deviceHeight)}px` : 'auto'; |
||||
|
return { |
||||
|
...unref(getProps), |
||||
|
loading: unref(getLoading), |
||||
|
columns: toRaw(unref(getPageColumns)), |
||||
|
rowKey: unref(getRowKey), |
||||
|
data: tableData, |
||||
|
size: unref(getTableSize), |
||||
|
remote: true, |
||||
|
'max-height': maxHeight, |
||||
|
}; |
||||
|
}); |
||||
|
|
||||
|
//获取分页信息 |
||||
|
const pagination = computed(() => toRaw(unref(getPaginationInfo))); |
||||
|
|
||||
|
function setProps(props: Partial<BasicTableProps>) { |
||||
|
innerPropsRef.value = { ...unref(innerPropsRef), ...props }; |
||||
|
} |
||||
|
|
||||
|
const setStriped = (value: boolean) => (isStriped.value = value); |
||||
|
|
||||
|
const tableAction = { |
||||
|
reload, |
||||
|
setColumns, |
||||
|
setLoading, |
||||
|
setProps, |
||||
|
getColumns, |
||||
|
getPageColumns, |
||||
|
getCacheColumns, |
||||
|
setCacheColumnsField, |
||||
|
emit, |
||||
|
}; |
||||
|
|
||||
|
const getCanResize = computed(() => { |
||||
|
const { canResize } = unref(getProps); |
||||
|
return canResize; |
||||
|
}); |
||||
|
|
||||
|
async function computeTableHeight() { |
||||
|
const table = unref(tableElRef); |
||||
|
if (!table) return; |
||||
|
if (!unref(getCanResize)) return; |
||||
|
const tableEl: any = table?.$el; |
||||
|
const headEl = tableEl.querySelector('.n-data-table-thead '); |
||||
|
const { bottomIncludeBody } = getViewportOffset(headEl); |
||||
|
const headerH = 64; |
||||
|
let paginationH = 2; |
||||
|
let marginH = 24; |
||||
|
if (!isBoolean(unref(pagination))) { |
||||
|
paginationEl = tableEl.querySelector('.n-data-table__pagination') as HTMLElement; |
||||
|
if (paginationEl) { |
||||
|
const offsetHeight = paginationEl.offsetHeight; |
||||
|
paginationH += offsetHeight || 0; |
||||
|
} else { |
||||
|
paginationH += 28; |
||||
|
} |
||||
|
} |
||||
|
let height = |
||||
|
bottomIncludeBody - (headerH + paginationH + marginH + (props.resizeHeightOffset || 0)); |
||||
|
const maxHeight = props.maxHeight; |
||||
|
height = maxHeight && maxHeight < height ? maxHeight : height; |
||||
|
deviceHeight.value = height; |
||||
|
} |
||||
|
|
||||
|
useWindowSizeFn(computeTableHeight, 280); |
||||
|
|
||||
|
onMounted(() => { |
||||
|
nextTick(() => { |
||||
|
computeTableHeight(); |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
createTableContext({ ...tableAction, wrapRef, getBindValues }); |
||||
|
|
||||
|
return { |
||||
|
...toRefs(state), |
||||
|
tableElRef, |
||||
|
getBindValues, |
||||
|
getDataSource, |
||||
|
densityOptions, |
||||
|
reload, |
||||
|
densitySelect, |
||||
|
updatePage, |
||||
|
updatePageSize, |
||||
|
pagination, |
||||
|
tableAction, |
||||
|
setStriped, |
||||
|
isStriped, |
||||
|
}; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
|
<style lang="less" scoped> |
||||
|
.table-toolbar { |
||||
|
display: flex; |
||||
|
justify-content: space-between; |
||||
|
padding: 0 0 16px 0; |
||||
|
|
||||
|
&-left { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: flex-start; |
||||
|
flex: 1; |
||||
|
|
||||
|
&-title { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: flex-start; |
||||
|
font-size: 16px; |
||||
|
font-weight: 600; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
&-right { |
||||
|
display: flex; |
||||
|
justify-content: flex-end; |
||||
|
flex: 1; |
||||
|
|
||||
|
&-icon { |
||||
|
margin-left: 12px; |
||||
|
font-size: 16px; |
||||
|
cursor: pointer; |
||||
|
color: var(--text-color); |
||||
|
|
||||
|
:hover { |
||||
|
color: #1890ff; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.table-toolbar-inner-popover-title { |
||||
|
padding: 2px 0; |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,41 @@ |
|||||
|
import type { Component } from 'vue'; |
||||
|
import { |
||||
|
NInput, |
||||
|
NSelect, |
||||
|
NCheckbox, |
||||
|
NInputNumber, |
||||
|
NSwitch, |
||||
|
NDatePicker, |
||||
|
NTimePicker, |
||||
|
} from 'naive-ui'; |
||||
|
import type { ComponentType } from './types/componentType'; |
||||
|
|
||||
|
export enum EventEnum { |
||||
|
NInput = 'on-input', |
||||
|
NInputNumber = 'on-input', |
||||
|
NSelect = 'on-update:value', |
||||
|
NSwitch = 'on-update:value', |
||||
|
NCheckbox = 'on-update:value', |
||||
|
NDatePicker = 'on-update:value', |
||||
|
NTimePicker = 'on-update:value', |
||||
|
} |
||||
|
|
||||
|
const componentMap = new Map<ComponentType, Component>(); |
||||
|
|
||||
|
componentMap.set('NInput', NInput); |
||||
|
componentMap.set('NInputNumber', NInputNumber); |
||||
|
componentMap.set('NSelect', NSelect); |
||||
|
componentMap.set('NSwitch', NSwitch); |
||||
|
componentMap.set('NCheckbox', NCheckbox); |
||||
|
componentMap.set('NDatePicker', NDatePicker); |
||||
|
componentMap.set('NTimePicker', NTimePicker); |
||||
|
|
||||
|
export function add(compName: ComponentType, component: Component) { |
||||
|
componentMap.set(compName, component); |
||||
|
} |
||||
|
|
||||
|
export function del(compName: ComponentType) { |
||||
|
componentMap.delete(compName); |
||||
|
} |
||||
|
|
||||
|
export { componentMap }; |
@ -0,0 +1,141 @@ |
|||||
|
<template> |
||||
|
<div class="tableAction"> |
||||
|
<div class="flex items-center justify-center"> |
||||
|
<template v-for="(action, index) in getActions" :key="`${index}-${action.label}`"> |
||||
|
<n-button v-bind="action" class="mx-2"> |
||||
|
{{ action.label }} |
||||
|
<template #icon v-if="action.hasOwnProperty('icon')"> |
||||
|
<n-icon :component="action.icon" /> |
||||
|
</template> |
||||
|
</n-button> |
||||
|
</template> |
||||
|
<n-dropdown |
||||
|
v-if="dropDownActions && getDropdownList.length" |
||||
|
trigger="hover" |
||||
|
:options="getDropdownList" |
||||
|
@select="select" |
||||
|
> |
||||
|
<slot name="more"></slot> |
||||
|
<n-button v-bind="getMoreProps" class="mx-2" v-if="!$slots.more" icon-placement="right"> |
||||
|
<div class="flex items-center"> |
||||
|
<span>更多</span> |
||||
|
<n-icon size="14" class="ml-1"> |
||||
|
<DownOutlined /> |
||||
|
</n-icon> |
||||
|
</div> |
||||
|
<!-- <template #icon>--> |
||||
|
<!-- --> |
||||
|
<!-- </template>--> |
||||
|
</n-button> |
||||
|
</n-dropdown> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
|
||||
|
<script lang="ts"> |
||||
|
import { defineComponent, PropType, computed, toRaw } from 'vue'; |
||||
|
import { ActionItem } from '@/components/Table'; |
||||
|
import { usePermission } from '@/hooks/web/usePermission'; |
||||
|
import { isBoolean, isFunction } from '@/utils/is'; |
||||
|
import { DownOutlined } from '@vicons/antd'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
name: 'TableAction', |
||||
|
components: { DownOutlined }, |
||||
|
props: { |
||||
|
actions: { |
||||
|
type: Array as PropType<ActionItem[]>, |
||||
|
default: null, |
||||
|
required: true, |
||||
|
}, |
||||
|
dropDownActions: { |
||||
|
type: Array as PropType<ActionItem[]>, |
||||
|
default: null, |
||||
|
}, |
||||
|
style: { |
||||
|
type: String as PropType<String>, |
||||
|
default: 'button', |
||||
|
}, |
||||
|
select: { |
||||
|
type: Function as PropType<Function>, |
||||
|
default: () => {}, |
||||
|
}, |
||||
|
}, |
||||
|
setup(props) { |
||||
|
const { hasPermission } = usePermission(); |
||||
|
|
||||
|
const actionType = |
||||
|
props.style === 'button' ? 'default' : props.style === 'text' ? 'primary' : 'default'; |
||||
|
const actionText = |
||||
|
props.style === 'button' ? undefined : props.style === 'text' ? true : undefined; |
||||
|
|
||||
|
const getMoreProps = computed(() => { |
||||
|
return { |
||||
|
text: actionText, |
||||
|
type: actionType, |
||||
|
size: 'small', |
||||
|
}; |
||||
|
}); |
||||
|
|
||||
|
const getDropdownList = computed(() => { |
||||
|
return (toRaw(props.dropDownActions) || []) |
||||
|
.filter((action) => { |
||||
|
return hasPermission(action.auth as string[]) && isIfShow(action); |
||||
|
}) |
||||
|
.map((action) => { |
||||
|
const { popConfirm } = action; |
||||
|
return { |
||||
|
size: 'small', |
||||
|
text: actionText, |
||||
|
type: actionType, |
||||
|
...action, |
||||
|
...popConfirm, |
||||
|
onConfirm: popConfirm?.confirm, |
||||
|
onCancel: popConfirm?.cancel, |
||||
|
}; |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
function isIfShow(action: ActionItem): boolean { |
||||
|
const ifShow = action.ifShow; |
||||
|
|
||||
|
let isIfShow = true; |
||||
|
|
||||
|
if (isBoolean(ifShow)) { |
||||
|
isIfShow = ifShow; |
||||
|
} |
||||
|
if (isFunction(ifShow)) { |
||||
|
isIfShow = ifShow(action); |
||||
|
} |
||||
|
return isIfShow; |
||||
|
} |
||||
|
|
||||
|
const getActions = computed(() => { |
||||
|
return (toRaw(props.actions) || []) |
||||
|
.filter((action) => { |
||||
|
return hasPermission(action.auth as string[]) && isIfShow(action); |
||||
|
}) |
||||
|
.map((action) => { |
||||
|
const { popConfirm } = action; |
||||
|
//需要展示什么风格,自己修改一下参数 |
||||
|
return { |
||||
|
size: 'small', |
||||
|
text: actionText, |
||||
|
type: actionType, |
||||
|
...action, |
||||
|
...(popConfirm || {}), |
||||
|
onConfirm: popConfirm?.confirm, |
||||
|
onCancel: popConfirm?.cancel, |
||||
|
enable: !!popConfirm, |
||||
|
}; |
||||
|
}); |
||||
|
}); |
||||
|
|
||||
|
return { |
||||
|
getActions, |
||||
|
getDropdownList, |
||||
|
getMoreProps, |
||||
|
}; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
@ -0,0 +1,47 @@ |
|||||
|
import type { FunctionalComponent, defineComponent } from 'vue'; |
||||
|
import type { ComponentType } from '../../types/componentType'; |
||||
|
import { componentMap } from '@/components/Table/src/componentMap'; |
||||
|
|
||||
|
import { h } from 'vue'; |
||||
|
|
||||
|
import { NPopover } from 'naive-ui'; |
||||
|
|
||||
|
export interface ComponentProps { |
||||
|
component: ComponentType; |
||||
|
rule: boolean; |
||||
|
popoverVisible: boolean; |
||||
|
ruleMessage: string; |
||||
|
} |
||||
|
|
||||
|
export const CellComponent: FunctionalComponent = ( |
||||
|
{ component = 'NInput', rule = true, ruleMessage, popoverVisible }: ComponentProps, |
||||
|
{ attrs } |
||||
|
) => { |
||||
|
const Comp = componentMap.get(component) as typeof defineComponent; |
||||
|
|
||||
|
const DefaultComp = h(Comp, attrs); |
||||
|
if (!rule) { |
||||
|
return DefaultComp; |
||||
|
} |
||||
|
return h( |
||||
|
NPopover, |
||||
|
{ 'display-directive': 'show', show: !!popoverVisible, manual: 'manual' }, |
||||
|
{ |
||||
|
trigger: () => DefaultComp, |
||||
|
default: () => |
||||
|
h( |
||||
|
'span', |
||||
|
{ |
||||
|
style: { |
||||
|
color: 'red', |
||||
|
width: '90px', |
||||
|
display: 'inline-block', |
||||
|
}, |
||||
|
}, |
||||
|
{ |
||||
|
default: () => ruleMessage, |
||||
|
} |
||||
|
), |
||||
|
} |
||||
|
); |
||||
|
}; |
@ -0,0 +1,418 @@ |
|||||
|
<template> |
||||
|
<div class="editable-cell"> |
||||
|
<div v-show="!isEdit" class="editable-cell-content" @click="handleEdit"> |
||||
|
{{ getValues }} |
||||
|
<n-icon class="edit-icon" v-if="!column.editRow"> |
||||
|
<FormOutlined /> |
||||
|
</n-icon> |
||||
|
</div> |
||||
|
<div class="flex editable-cell-content" v-show="isEdit" v-click-outside="onClickOutside"> |
||||
|
<div class="editable-cell-content-comp"> |
||||
|
<CellComponent |
||||
|
v-bind="getComponentProps" |
||||
|
:component="getComponent" |
||||
|
:popoverVisible="getRuleVisible" |
||||
|
:ruleMessage="ruleMessage" |
||||
|
:rule="getRule" |
||||
|
:class="getWrapperClass" |
||||
|
ref="elRef" |
||||
|
@options-change="handleOptionsChange" |
||||
|
@pressEnter="handleEnter" |
||||
|
/> |
||||
|
</div> |
||||
|
<div class="editable-cell-action" v-if="!getRowEditable"> |
||||
|
<n-icon class="mx-2 cursor-pointer"> |
||||
|
<CheckOutlined @click="handleSubmit" /> |
||||
|
</n-icon> |
||||
|
<n-icon class="mx-2 cursor-pointer"> |
||||
|
<CloseOutlined @click="handleCancel" /> |
||||
|
</n-icon> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</template> |
||||
|
<script lang="ts"> |
||||
|
import type { PropType } from 'vue'; |
||||
|
import type { BasicColumn } from '../../types/table'; |
||||
|
import type { EditRecordRow } from './index'; |
||||
|
|
||||
|
import { defineComponent, ref, unref, nextTick, computed, watchEffect, toRaw } from 'vue'; |
||||
|
import { FormOutlined, CloseOutlined, CheckOutlined } from '@vicons/antd'; |
||||
|
import { CellComponent } from './CellComponent'; |
||||
|
|
||||
|
import { useTableContext } from '../../hooks/useTableContext'; |
||||
|
|
||||
|
import clickOutside from '@/directives/clickOutside'; |
||||
|
|
||||
|
import { propTypes } from '@/utils/propTypes'; |
||||
|
import { isString, isBoolean, isFunction, isNumber, isArray } from '@/utils/is'; |
||||
|
import { createPlaceholderMessage } from './helper'; |
||||
|
import { set, omit } from 'lodash-es'; |
||||
|
import { EventEnum } from '@/components/Table/src/componentMap'; |
||||
|
|
||||
|
import { parseISO, format } from 'date-fns'; |
||||
|
|
||||
|
export default defineComponent({ |
||||
|
name: 'EditableCell', |
||||
|
components: { FormOutlined, CloseOutlined, CheckOutlined, CellComponent }, |
||||
|
directives: { |
||||
|
clickOutside, |
||||
|
}, |
||||
|
props: { |
||||
|
value: { |
||||
|
type: [String, Number, Boolean, Object] as PropType<string | number | boolean | Recordable>, |
||||
|
default: '', |
||||
|
}, |
||||
|
record: { |
||||
|
type: Object as PropType<EditRecordRow>, |
||||
|
}, |
||||
|
column: { |
||||
|
type: Object as PropType<BasicColumn>, |
||||
|
default: () => ({}), |
||||
|
}, |
||||
|
index: propTypes.number, |
||||
|
}, |
||||
|
setup(props) { |
||||
|
const table = useTableContext(); |
||||
|
const isEdit = ref(false); |
||||
|
const elRef = ref(); |
||||
|
const ruleVisible = ref(false); |
||||
|
const ruleMessage = ref(''); |
||||
|
const optionsRef = ref<LabelValueOptions>([]); |
||||
|
const currentValueRef = ref<any>(props.value); |
||||
|
const defaultValueRef = ref<any>(props.value); |
||||
|
|
||||
|
// const { prefixCls } = useDesign('editable-cell'); |
||||
|
|
||||
|
const getComponent = computed(() => props.column?.editComponent || 'NInput'); |
||||
|
const getRule = computed(() => props.column?.editRule); |
||||
|
|
||||
|
const getRuleVisible = computed(() => { |
||||
|
return unref(ruleMessage) && unref(ruleVisible); |
||||
|
}); |
||||
|
|
||||
|
const getIsCheckComp = computed(() => { |
||||
|
const component = unref(getComponent); |
||||
|
return ['NCheckbox', 'NRadio'].includes(component); |
||||
|
}); |
||||
|
|
||||
|
const getComponentProps = computed(() => { |
||||
|
const compProps = props.column?.editComponentProps ?? {}; |
||||
|
const editComponent = props.column?.editComponent ?? null; |
||||
|
const component = unref(getComponent); |
||||
|
const apiSelectProps: Recordable = {}; |
||||
|
|
||||
|
const isCheckValue = unref(getIsCheckComp); |
||||
|
|
||||
|
let valueField = isCheckValue ? 'checked' : 'value'; |
||||
|
const val = unref(currentValueRef); |
||||
|
|
||||
|
let value = isCheckValue ? (isNumber(val) && isBoolean(val) ? val : !!val) : val; |
||||
|
|
||||
|
//TODO 特殊处理 NDatePicker 可能要根据项目 规范自行调整代码 |
||||
|
if (component === 'NDatePicker') { |
||||
|
if (isString(value)) { |
||||
|
if (compProps.valueFormat) { |
||||
|
valueField = 'formatted-value'; |
||||
|
} else { |
||||
|
value = parseISO(value as any).getTime(); |
||||
|
} |
||||
|
} else if (isArray(value)) { |
||||
|
if (compProps.valueFormat) { |
||||
|
valueField = 'formatted-value'; |
||||
|
} else { |
||||
|
value = value.map((item) => parseISO(item).getTime()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const onEvent: any = editComponent ? EventEnum[editComponent] : undefined; |
||||
|
|
||||
|
return { |
||||
|
placeholder: createPlaceholderMessage(unref(getComponent)), |
||||
|
...apiSelectProps, |
||||
|
...omit(compProps, 'onChange'), |
||||
|
[onEvent]: handleChange, |
||||
|
[valueField]: value, |
||||
|
}; |
||||
|
}); |
||||
|
|
||||
|
const getValues = computed(() => { |
||||
|
const { editComponentProps, editValueMap } = props.column; |
||||
|
|
||||
|
const value = unref(currentValueRef); |
||||
|
|
||||
|
if (editValueMap && isFunction(editValueMap)) { |
||||
|
return editValueMap(value); |
||||
|
} |
||||
|
|
||||
|
const component = unref(getComponent); |
||||
|
if (!component.includes('NSelect')) { |
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
const options: LabelValueOptions = editComponentProps?.options ?? (unref(optionsRef) || []); |
||||
|
const option = options.find((item) => `${item.value}` === `${value}`); |
||||
|
|
||||
|
return option?.label ?? value; |
||||
|
}); |
||||
|
|
||||
|
const getWrapperClass = computed(() => { |
||||
|
const { align = 'center' } = props.column; |
||||
|
return `edit-cell-align-${align}`; |
||||
|
}); |
||||
|
|
||||
|
const getRowEditable = computed(() => { |
||||
|
const { editable } = props.record || {}; |
||||
|
return !!editable; |
||||
|
}); |
||||
|
|
||||
|
watchEffect(() => { |
||||
|
defaultValueRef.value = props.value; |
||||
|
}); |
||||
|
|
||||
|
watchEffect(() => { |
||||
|
const { editable } = props.column; |
||||
|
if (isBoolean(editable) || isBoolean(unref(getRowEditable))) { |
||||
|
isEdit.value = !!editable || unref(getRowEditable); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
function handleEdit() { |
||||
|
if (unref(getRowEditable) || unref(props.column?.editRow)) return; |
||||
|
ruleMessage.value = ''; |
||||
|
isEdit.value = true; |
||||
|
nextTick(() => { |
||||
|
const el = unref(elRef); |
||||
|
el?.focus?.(); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
async function handleChange(e: any) { |
||||
|
const component = unref(getComponent); |
||||
|
const compProps = props.column?.editComponentProps ?? {}; |
||||
|
if (!e) { |
||||
|
currentValueRef.value = e; |
||||
|
} else if (e?.target && Reflect.has(e.target, 'value')) { |
||||
|
currentValueRef.value = (e as ChangeEvent).target.value; |
||||
|
} else if (component === 'NCheckbox') { |
||||
|
currentValueRef.value = (e as ChangeEvent).target.checked; |
||||
|
} else if (isString(e) || isBoolean(e) || isNumber(e)) { |
||||
|
currentValueRef.value = e; |
||||
|
} |
||||
|
|
||||
|
//TODO 特殊处理 NDatePicker 可能要根据项目 规范自行调整代码 |
||||
|
if (component === 'NDatePicker') { |
||||
|
if (isNumber(currentValueRef.value)) { |
||||
|
if (compProps.valueFormat) { |
||||
|
currentValueRef.value = format(currentValueRef.value, compProps.valueFormat); |
||||
|
} |
||||
|
} else if (isArray(currentValueRef.value)) { |
||||
|
if (compProps.valueFormat) { |
||||
|
currentValueRef.value = currentValueRef.value.map((item) => { |
||||
|
format(item, compProps.valueFormat); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const onChange = props.column?.editComponentProps?.onChange; |
||||
|
if (onChange && isFunction(onChange)) onChange(...arguments); |
||||
|
|
||||
|
table.emit?.('edit-change', { |
||||
|
column: props.column, |
||||
|
value: unref(currentValueRef), |
||||
|
record: toRaw(props.record), |
||||
|
}); |
||||
|
await handleSubmiRule(); |
||||
|
} |
||||
|
|
||||
|
async function handleSubmiRule() { |
||||
|
const { column, record } = props; |
||||
|
const { editRule } = column; |
||||
|
const currentValue = unref(currentValueRef); |
||||
|
|
||||
|
if (editRule) { |
||||
|
if (isBoolean(editRule) && !currentValue && !isNumber(currentValue)) { |
||||
|
ruleVisible.value = true; |
||||
|
const component = unref(getComponent); |
||||
|
ruleMessage.value = createPlaceholderMessage(component); |
||||
|
return false; |
||||
|
} |
||||
|
if (isFunction(editRule)) { |
||||
|
const res = await editRule(currentValue, record as Recordable); |
||||
|
if (!!res) { |
||||
|
ruleMessage.value = res; |
||||
|
ruleVisible.value = true; |
||||
|
return false; |
||||
|
} else { |
||||
|
ruleMessage.value = ''; |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
ruleMessage.value = ''; |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
async function handleSubmit(needEmit = true, valid = true) { |
||||
|
if (valid) { |
||||
|
const isPass = await handleSubmiRule(); |
||||
|
if (!isPass) return false; |
||||
|
} |
||||
|
|
||||
|
const { column, index, record } = props; |
||||
|
if (!record) return false; |
||||
|
const { key } = column; |
||||
|
const value = unref(currentValueRef); |
||||
|
if (!key) return; |
||||
|
|
||||
|
const dataKey = key as string; |
||||
|
|
||||
|
set(record, dataKey, value); |
||||
|
//const record = await table.updateTableData(index, dataKey, value); |
||||
|
needEmit && table.emit?.('edit-end', { record, index, key, value }); |
||||
|
isEdit.value = false; |
||||
|
} |
||||
|
|
||||
|
async function handleEnter() { |
||||
|
if (props.column?.editRow) { |
||||
|
return; |
||||
|
} |
||||
|
await handleSubmit(); |
||||
|
} |
||||
|
|
||||
|
function handleCancel() { |
||||
|
isEdit.value = false; |
||||
|
currentValueRef.value = defaultValueRef.value; |
||||
|
const { column, index, record } = props; |
||||
|
const { key } = column; |
||||
|
ruleVisible.value = true; |
||||
|
ruleMessage.value = ''; |
||||
|
table.emit?.('edit-cancel', { |
||||
|
record, |
||||
|
index, |
||||
|
key: key, |
||||
|
value: unref(currentValueRef), |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function onClickOutside() { |
||||
|
if (props.column?.editable || unref(getRowEditable)) { |
||||
|
return; |
||||
|
} |
||||
|
const component = unref(getComponent); |
||||
|
|
||||
|
if (component.includes('NInput')) { |
||||
|
handleCancel(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// only ApiSelect |
||||
|
function handleOptionsChange(options: LabelValueOptions) { |
||||
|
optionsRef.value = options; |
||||
|
} |
||||
|
|
||||
|
function initCbs(cbs: 'submitCbs' | 'validCbs' | 'cancelCbs', handle: Fn) { |
||||
|
if (props.record) { |
||||
|
/* eslint-disable */ |
||||
|
isArray(props.record[cbs]) |
||||
|
? props.record[cbs]?.push(handle) |
||||
|
: (props.record[cbs] = [handle]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (props.record) { |
||||
|
initCbs('submitCbs', handleSubmit); |
||||
|
initCbs('validCbs', handleSubmiRule); |
||||
|
initCbs('cancelCbs', handleCancel); |
||||
|
|
||||
|
if (props.column.key) { |
||||
|
if (!props.record.editValueRefs) props.record.editValueRefs = {}; |
||||
|
props.record.editValueRefs[props.column.key] = currentValueRef; |
||||
|
} |
||||
|
/* eslint-disable */ |
||||
|
props.record.onCancelEdit = () => { |
||||
|
isArray(props.record?.cancelCbs) && props.record?.cancelCbs.forEach((fn) => fn()); |
||||
|
}; |
||||
|
/* eslint-disable */ |
||||
|
props.record.onSubmitEdit = async () => { |
||||
|
if (isArray(props.record?.submitCbs)) { |
||||
|
const validFns = (props.record?.validCbs || []).map((fn) => fn()); |
||||
|
|
||||
|
const res = await Promise.all(validFns); |
||||
|
|
||||
|
const pass = res.every((item) => !!item); |
||||
|
|
||||
|
if (!pass) return; |
||||
|
const submitFns = props.record?.submitCbs || []; |
||||
|
submitFns.forEach((fn) => fn(false, false)); |
||||
|
table.emit?.('edit-row-end'); |
||||
|
return true; |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
return { |
||||
|
isEdit, |
||||
|
handleEdit, |
||||
|
currentValueRef, |
||||
|
handleSubmit, |
||||
|
handleChange, |
||||
|
handleCancel, |
||||
|
elRef, |
||||
|
getComponent, |
||||
|
getRule, |
||||
|
onClickOutside, |
||||
|
ruleMessage, |
||||
|
getRuleVisible, |
||||
|
getComponentProps, |
||||
|
handleOptionsChange, |
||||
|
getWrapperClass, |
||||
|
getRowEditable, |
||||
|
getValues, |
||||
|
handleEnter, |
||||
|
// getSize, |
||||
|
}; |
||||
|
}, |
||||
|
}); |
||||
|
</script> |
||||
|
|
||||
|
<style lang="less"> |
||||
|
.editable-cell { |
||||
|
&-content { |
||||
|
position: relative; |
||||
|
overflow-wrap: break-word; |
||||
|
word-break: break-word; |
||||
|
overflow: hidden; |
||||
|
white-space: nowrap; |
||||
|
text-overflow: ellipsis; |
||||
|
|
||||
|
&-comp { |
||||
|
flex: 1; |
||||
|
} |
||||
|
|
||||
|
.edit-icon { |
||||
|
font-size: 14px; |
||||
|
//position: absolute; |
||||
|
//top: 4px; |
||||
|
//right: 0; |
||||
|
display: none; |
||||
|
width: 20px; |
||||
|
cursor: pointer; |
||||
|
} |
||||
|
|
||||
|
&:hover { |
||||
|
.edit-icon { |
||||
|
display: inline-block; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
&-action { |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
} |
||||
|
} |
||||
|
</style> |
@ -0,0 +1,15 @@ |
|||||
|
import { ComponentType } from '../../types/componentType'; |
||||
|
|
||||
|
/** |
||||
|
* @description: 生成placeholder |
||||
|
*/ |
||||
|
export function createPlaceholderMessage(component: ComponentType) { |
||||
|
if (component === 'NInput') return '请输入'; |
||||
|
if ( |
||||
|
['NPicker', 'NSelect', 'NCheckbox', 'NRadio', 'NSwitch', 'NDatePicker', 'NTimePicker'].includes( |
||||
|
component |
||||
|
) |
||||
|
) |
||||
|
return '请选择'; |
||||
|
return ''; |
||||
|
} |