提交 5e8ef2f6 编写于 作者: V vben

feat: 添加 defineOptions

上级 8e5a6b7c
......@@ -37,6 +37,8 @@
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-unused-imports": "^2.0.0",
"eslint-plugin-vue": "^9.10.0",
"vue-eslint-parser": "^9.1.1"
}
......
......@@ -17,7 +17,14 @@ export default {
createDefaultProgram: false,
extraFileExtensions: ['.vue'],
},
plugins: ['vue', '@typescript-eslint', 'import'],
plugins: [
'vue',
'@typescript-eslint',
'import',
// TODO: 改造完成后开启
// 'unused-imports',
// 'simple-import-sort',
],
extends: [
'eslint:recommended',
'plugin:vue/vue3-recommended',
......@@ -30,10 +37,26 @@ export default {
'no-use-before-define': 'off',
'space-before-function-paren': 'off',
// TODO: 改造完成后开启
// 'simple-import-sort/imports': 'error',
// 'simple-import-sort/exports': 'error',
'import/first': 'error',
'import/newline-after-import': 'error',
'import/no-duplicates': 'error',
// 'unused-imports/no-unused-imports': 'error',
// 'unused-imports/no-unused-vars': [
// 'warn',
// { vars: 'all', varsIgnorePattern: '^_', args: 'after-used', argsIgnorePattern: '^_' },
// ],
'@typescript-eslint/no-unused-vars': [
'error',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'@typescript-eslint/ban-ts-ignore': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/no-explicit-any': 'off',
......@@ -44,13 +67,7 @@ export default {
'@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',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'@typescript-eslint/no-unused-vars': 'off',
'vue/script-setup-uses-vars': 'error',
'vue/no-reserved-component-names': 'off',
'vue/custom-event-name-casing': 'off',
......@@ -87,4 +104,5 @@ export default {
// },
// ],
},
globals: { defineOptions: 'readonly' },
};
......@@ -19,6 +19,8 @@
"node-server.json"
],
"dependencies": {
"@types/node": "^18.15.11"
"@types/node": "^18.15.11",
"unplugin-vue-define-options": "^1.3.3",
"vite": "^4.3.0-beta.2"
}
}
{
"$schema": "https://json.schemastore.org/tsconfig",
"display": "Vue Library",
"display": "Vue Application",
"extends": "./base.json",
"compilerOptions": {
"jsx": "preserve",
"lib": ["ESNext", "DOM"],
"noImplicitAny": false
}
}
......@@ -32,11 +32,13 @@
},
"dependencies": {
"@ant-design/colors": "^7.0.0",
"vite": "^4.3.0-beta.1"
"vite": "^4.3.0-beta.2"
},
"devDependencies": {
"@types/fs-extra": "^11.0.1",
"ant-design-vue": "^3.2.16",
"@vitejs/plugin-vue": "^4.1.0",
"@vitejs/plugin-vue-jsx": "^3.0.1",
"ant-design-vue": "^3.2.17",
"dayjs": "^1.11.7",
"dotenv": "^16.0.3",
"fs-extra": "^11.1.1",
......@@ -46,6 +48,7 @@
"rollup-plugin-visualizer": "^5.9.0",
"sass": "^1.60.0",
"unocss": "^0.50.6",
"unplugin-vue-define-options": "^1.3.3",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-dts": "^2.2.0",
"vite-plugin-html": "^3.2.0",
......
......@@ -8,6 +8,8 @@ import { createAppConfigPlugin } from './appConfig';
import vue from '@vitejs/plugin-vue';
import vueJsx from '@vitejs/plugin-vue-jsx';
import purgeIcons from 'vite-plugin-purge-icons';
// @ts-ignore
import DefineOptions from 'unplugin-vue-define-options/vite';
interface Options {
isBuild: boolean;
......@@ -18,7 +20,7 @@ interface Options {
}
async function createPlugins({ isBuild, root, enableMock, compress, enableAnalyze }: Options) {
const vitePlugins: (PluginOption | PluginOption[])[] = [vue(), vueJsx()];
const vitePlugins: (PluginOption | PluginOption[])[] = [vue(), vueJsx(), DefineOptions()];
const appConfigPlugin = await createAppConfigPlugin({ root, isBuild });
vitePlugins.push(appConfigPlugin);
......
// life-cycle
export * from './lifecycle/onMountedOrActivated';
export * from './onMountedOrActivated';
export * from './useAttrs';
import { getCurrentInstance, reactive, shallowRef, watchEffect } from 'vue';
import type { Ref } from 'vue';
import { type Recordable } from '@vben/types';
interface Params {
interface Options {
excludeListeners?: boolean;
excludeKeys?: string[];
excludeDefaultKeys?: boolean;
......@@ -10,15 +10,15 @@ interface Params {
const DEFAULT_EXCLUDE_KEYS = ['class', 'style'];
const LISTENER_PREFIX = /^on[A-Z]/;
export function entries<T>(obj: Recordable<T>): [string, T][] {
function entries<T>(obj: Recordable<T>): [string, T][] {
return Object.keys(obj).map((key: string) => [key, obj[key]]);
}
export function useAttrs(params: Params = {}): Ref<Recordable> | {} {
function useAttrs(options: Options = {}): Recordable<any> {
const instance = getCurrentInstance();
if (!instance) return {};
const { excludeListeners = false, excludeKeys = [], excludeDefaultKeys = true } = params;
const { excludeListeners = false, excludeKeys = [], excludeDefaultKeys = true } = options;
const attrs = shallowRef({});
const allExcludeKeys = excludeKeys.concat(excludeDefaultKeys ? DEFAULT_EXCLUDE_KEYS : []);
......@@ -32,10 +32,12 @@ export function useAttrs(params: Params = {}): Ref<Recordable> | {} {
}
return acm;
}, {} as Recordable);
}, {} as Recordable<any>);
attrs.value = res;
});
return attrs;
}
export { useAttrs };
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/ts-config/vue.json",
"extends": "@vben/ts-config/vue-app.json",
"include": ["src"]
}
......@@ -13,4 +13,34 @@ type AnyPromiseFunction = (...arg: any) => PromiseLike<any>;
*/
type AnyNormalFunction = (...arg: any) => any;
export { type AnyFunction, type AnyPromiseFunction, type AnyNormalFunction };
/**
* T | null 包装
*/
type Nullable<T> = T | null;
/**
* T | Not null 包装
*/
type NonNullable<T> = T extends null | undefined ? never : T;
/**
* 字符串类型对象
*/
type Recordable<T> = Record<string, T>;
/**
* 字符串类型对象(只读)
*/
type ReadonlyRecordable<T = any> = {
readonly [key: string]: T;
};
export {
type AnyFunction,
type AnyPromiseFunction,
type AnyNormalFunction,
type Nullable,
type NonNullable,
type Recordable,
type ReadonlyRecordable,
};
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/ts-config/vue.json",
"extends": "@vben/ts-config/vue-app.json",
"include": ["src"]
}
此差异已折叠。
......@@ -8,11 +8,11 @@
<script lang="ts" setup>
import { ConfigProvider } from 'ant-design-vue';
import { AppProvider } from '/@/components/Application';
import { useTitle } from '/@/hooks/web/useTitle';
import { useLocale } from '/@/locales/useLocale';
import { AppProvider } from '@/components/Application';
import { useTitle } from '@/hooks/web/useTitle';
import { useLocale } from '@/locales/useLocale';
import 'dayjs/locale/zh-cn';
// support Multi-language
const { getAntdLocale } = useLocale();
......
......@@ -8,20 +8,18 @@
</Button>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
<script lang="ts" setup>
import { Button } from 'ant-design-vue';
export default defineComponent({
import { computed, unref } from 'vue';
import Icon from '/@/components/Icon/src/Icon.vue';
import { buttonProps } from './props';
import { useAttrs } from '@vben/hooks';
defineOptions({
name: 'AButton',
extends: Button,
inheritAttrs: false,
});
</script>
<script lang="ts" setup>
import { computed, unref } from 'vue';
import Icon from '/@/components/Icon/src/Icon.vue';
import { buttonProps } from './props';
import { useAttrs } from '/@/hooks/core/useAttrs';
const props = defineProps(buttonProps);
// get component class
......
......@@ -4,7 +4,7 @@
import { Popconfirm } from 'ant-design-vue';
import { extendSlots } from '/@/utils/helper/tsxHelper';
import { omit } from 'lodash-es';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { useAttrs } from '@vben/hooks';
import { useI18n } from '/@/hooks/web/useI18n';
const props = {
......@@ -39,7 +39,7 @@
return () => {
const bindValues = omit(unref(getBindValues), 'icon');
const btnBind = omit(bindValues, 'title') as Recordable;
const btnBind = omit(bindValues, 'title') as any;
if (btnBind.disabled) btnBind.color = '';
const Button = h(BasicButton, btnBind, extendSlots(slots));
......
<script lang="tsx">
import type { DescriptionProps, DescInstance, DescItem } from './typing';
import type { DescriptionsProps } from 'ant-design-vue/es/descriptions/index';
import type { CSSProperties } from 'vue';
import type { CollapseContainerOptions } from '/@/components/Container/index';
import { defineComponent, computed, ref, unref, toRefs } from 'vue';
import {
type CSSProperties,
type PropType,
defineComponent,
computed,
ref,
unref,
toRefs,
} from 'vue';
import { get } from 'lodash-es';
import { Descriptions } from 'ant-design-vue';
import { CollapseContainer } from '/@/components/Container/index';
import { useDesign } from '/@/hooks/web/useDesign';
import { isFunction } from '/@/utils/is';
import { getSlot } from '/@/utils/helper/tsxHelper';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { useAttrs } from '@vben/hooks';
const props = {
useCollapse: { type: Boolean, default: true },
......@@ -22,7 +29,7 @@
},
bordered: { type: Boolean, default: true },
column: {
type: [Number, Object] as PropType<number | Recordable>,
type: [Number, Object],
default: () => {
return { xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 };
},
......@@ -52,7 +59,7 @@
const getMergeProps = computed(() => {
return {
...props,
...(unref(propsRef) as Recordable),
...(unref(propsRef) as any),
} as DescriptionProps;
});
......@@ -89,7 +96,10 @@
*/
function setDescProps(descProps: Partial<DescriptionProps>): void {
// Keep the last setDrawerProps
propsRef.value = { ...(unref(propsRef) as Recordable), ...descProps } as Recordable;
propsRef.value = {
...(unref(propsRef) as Record<string, any>),
...descProps,
} as Record<string, any>;
}
// Prevent line breaks
......@@ -121,6 +131,7 @@
return null;
}
const getField = get(_data, field);
// eslint-disable-next-line
if (getField && !toRefs(_data).hasOwnProperty(field)) {
return isFunction(render) ? render('', _data) : '';
}
......
......@@ -52,7 +52,7 @@
import { ScrollContainer } from '/@/components/Container';
import { basicProps } from './props';
import { useDesign } from '/@/hooks/web/useDesign';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { useAttrs } from '@vben/hooks';
export default defineComponent({
components: { Drawer, ScrollContainer, DrawerFooter, DrawerHeader },
......@@ -68,7 +68,7 @@
const { prefixVar, prefixCls } = useDesign('basic-drawer');
const drawerInstance: DrawerInstance = {
setDrawerProps: setDrawerProps,
setDrawerProps: setDrawerProps as any,
emitVisible: undefined,
};
......
......@@ -19,14 +19,15 @@
</RadioGroup>
</template>
<script lang="ts">
import { defineComponent, PropType, ref, watchEffect, computed, unref, watch } from 'vue';
import { defineComponent, type PropType, ref, watchEffect, computed, unref, watch } from 'vue';
import { Radio } from 'ant-design-vue';
import { isFunction } from '/@/utils/is';
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { useAttrs } from '@vben/hooks';
import { propTypes } from '/@/utils/propTypes';
import { get, omit } from 'lodash-es';
import { useI18n } from '/@/hooks/web/useI18n';
type OptionsItem = { label: string; value: string | number | boolean; disabled?: boolean };
export default defineComponent({
......@@ -38,11 +39,11 @@
},
props: {
api: {
type: Function as PropType<(arg?: Recordable | string) => Promise<OptionsItem[]>>,
type: Function as PropType<(arg?: any | string) => Promise<OptionsItem[]>>,
default: null,
},
params: {
type: [Object, String] as PropType<Recordable | string>,
type: [Object, String] as PropType<any | string>,
default: () => ({}),
},
value: {
......@@ -73,7 +74,7 @@
const getOptions = computed(() => {
const { labelField, valueField, numberToString } = props;
return unref(options).reduce((prev, next: Recordable) => {
return unref(options).reduce((prev, next: any) => {
if (next) {
const value = next[valueField];
prev.push({
......
......@@ -25,7 +25,7 @@
import { Select } from 'ant-design-vue';
import { isFunction } from '/@/utils/is';
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { useAttrs } from '@vben/hooks';
import { get, omit } from 'lodash-es';
import { LoadingOutlined } from '@ant-design/icons-vue';
import { useI18n } from '/@/hooks/web/useI18n';
......@@ -44,7 +44,7 @@
value: [Array, Object, String, Number],
numberToString: propTypes.bool,
api: {
type: Function as PropType<(arg?: Recordable) => Promise<OptionsItem[]>>,
type: Function as PropType<(arg?: any) => Promise<OptionsItem[]>>,
default: null,
},
// api params
......@@ -71,7 +71,7 @@
const getOptions = computed(() => {
const { labelField, valueField, numberToString } = props;
return unref(options).reduce((prev, next: Recordable) => {
return unref(options).reduce((prev, next: any) => {
if (next) {
const value = get(next, valueField);
prev.push({
......
......@@ -15,7 +15,7 @@
import { Radio } from 'ant-design-vue';
import { isString } from '/@/utils/is';
import { useRuleFormItem } from '/@/hooks/component/useFormItem';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { useAttrs } from '@vben/hooks';
type OptionsItem = { label: string; value: string | number | boolean; disabled?: boolean };
type RadioItem = string | OptionsItem;
......
......@@ -2,13 +2,13 @@ import { Modal } from 'ant-design-vue';
import { defineComponent, toRefs, unref } from 'vue';
import { basicProps } from '../props';
import { useModalDragMove } from '../hooks/useModalDrag';
import { useAttrs } from '/@/hooks/core/useAttrs';
import { useAttrs } from '@vben/hooks';
import { extendSlots } from '/@/utils/helper/tsxHelper';
export default defineComponent({
name: 'Modal',
inheritAttrs: false,
props: basicProps,
props: basicProps as any,
emits: ['cancel'],
setup(props, { slots, emit }) {
const { visible, draggable, destroyOnClose } = toRefs(props);
......
import 'uno.css';
import '/@/design/index.less';
import '/@/components/VxeTable/src/css/index.scss';
import '@/design/index.less';
import '@/components/VxeTable/src/css/index.scss';
import 'ant-design-vue/dist/antd.css';
// Register icon sprite
import 'virtual:svg-icons-register';
import App from './App.vue';
import { createApp } from 'vue';
import { initAppConfigStore } from '/@/logics/initAppConfig';
import { setupErrorHandle } from '/@/logics/error-handle';
import { router, setupRouter } from '/@/router';
import { setupRouterGuard } from '/@/router/guard';
import { setupStore } from '/@/store';
import { setupGlobDirectives } from '/@/directives';
import { setupI18n } from '/@/locales/setupI18n';
import { registerGlobComp } from '/@/components/registerGlobComp';
import { registerGlobComp } from '@/components/registerGlobComp';
import { setupGlobDirectives } from '@/directives';
import { setupI18n } from '@/locales/setupI18n';
import { setupErrorHandle } from '@/logics/error-handle';
import { initAppConfigStore } from '@/logics/initAppConfig';
import { router, setupRouter } from '@/router';
import { setupRouterGuard } from '@/router/guard';
import { setupStore } from '@/store';
import App from './App.vue';
async function bootstrap() {
const app = createApp(App);
......
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/ts-config/vue.json",
"extends": "@vben/ts-config/vue-app.json",
"compilerOptions": {
"baseUrl": "./",
"types": ["vite/client"],
"baseUrl": ".",
"types": ["vite/client", "unplugin-vue-define-options/macros-global"],
"paths": {
"/@/*": ["src/*"],
"/#/*": ["types/*"],
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册