Kaynağa Gözat

chore: Fix ts type error (#3100)

* chore: fix onUploadProgress params type error

* fix(BasicButton): extends type error

* fix: useFormRules 类型问题

* fix: IFormConfig 类型问题

* chore: 设定CollapseItem list参数的类型

* chore: 修复sliderSpan类型错误

* chore: 改写成setup组件

* fix: static func type error

* chore: 设定listener 函数 evt类型为Event

* chore(props): 消除ts类型错误

* chore: 移除多余的类型转换

* Update domUtils.ts

* chore: 消除iconPicker类型错误

* Update domUtils.ts

* chore(clickOutside): 消除类型错误

* Update repeatClick.ts

* Update index.ts

* chore: 补全参数类型

* fix(Cropper): avatar uploadapi 类型问题
invalid w 1 yıl önce
ebeveyn
işleme
1e95706f8b

+ 2 - 1
src/api/sys/upload.ts

@@ -2,6 +2,7 @@ import { UploadApiResult } from './model/uploadModel';
 import { defHttp } from '/@/utils/http/axios';
 import { UploadFileParams } from '/#/axios';
 import { useGlobSetting } from '/@/hooks/setting';
+import { AxiosProgressEvent } from 'axios';
 
 const { uploadUrl = '' } = useGlobSetting();
 
@@ -10,7 +11,7 @@ const { uploadUrl = '' } = useGlobSetting();
  */
 export function uploadApi(
   params: UploadFileParams,
-  onUploadProgress: (progressEvent: ProgressEvent) => void,
+  onUploadProgress: (progressEvent: AxiosProgressEvent) => void,
 ) {
   return defHttp.uploadFile<UploadApiResult>(
     {

+ 2 - 2
src/components/Button/src/BasicButton.vue

@@ -10,14 +10,14 @@
 
 <script lang="ts" setup>
   import { Button } from 'ant-design-vue';
-  import { computed, unref } from 'vue';
+  import { ComponentOptionsMixin, computed, unref } from 'vue';
   import Icon from '@/components/Icon/Icon.vue';
   import { buttonProps } from './props';
   import { useAttrs } from '@vben/hooks';
 
   defineOptions({
     name: 'AButton',
-    extends: Button,
+    extends: Button as ComponentOptionsMixin,
     inheritAttrs: false,
   });
 

+ 4 - 4
src/components/CardList/src/CardList.vue

@@ -157,22 +157,22 @@
     pageSize,
     current: page,
     total,
-    showTotal: (total) => `总 ${total} 条`,
+    showTotal: (total: number) => `总 ${total} 条`,
     onChange: pageChange,
     onShowSizeChange: pageSizeChange,
   });
 
-  function pageChange(p, pz) {
+  function pageChange(p: number, pz: number) {
     page.value = p;
     pageSize.value = pz;
     fetch();
   }
-  function pageSizeChange(_current, size) {
+  function pageSizeChange(_current, size: number) {
     pageSize.value = size;
     fetch();
   }
 
-  async function handleDelete(id) {
+  async function handleDelete(id: number) {
     emit('delete', id);
   }
 </script>

+ 4 - 1
src/components/Cropper/src/CropperAvatar.vue

@@ -54,7 +54,10 @@
     showBtn: { type: Boolean, default: true },
     btnProps: { type: Object as PropType<ButtonProps> },
     btnText: { type: String, default: '' },
-    uploadApi: { type: Function as PropType<({ file: Blob, name: string }) => Promise<void>> },
+    uploadApi: {
+      type: Function as PropType<({ file, name }: { file: Blob; name: string }) => Promise<void>>,
+    },
+
     size: { type: Number, default: 5 },
   };
 

+ 17 - 9
src/components/Icon/src/IconPicker.vue

@@ -73,7 +73,6 @@
   import SvgIcon from './SvgIcon.vue';
 
   import iconsData from '../data/icons.data';
-  import { propTypes } from '/@/utils/propTypes';
   import { usePagination } from '/@/hooks/web/usePagination';
   import { useDebounceFn } from '@vueuse/core';
   import { useI18n } from '/@/hooks/web/useI18n';
@@ -98,15 +97,23 @@
   }
 
   function getSvgIcons() {
-    return svgIcons.map((icon) => icon.replace('icon-', ''));
+    return svgIcons.map((icon: string) => icon.replace('icon-', ''));
   }
 
-  const props = defineProps({
-    value: propTypes.string,
-    width: propTypes.string.def('100%'),
-    pageSize: propTypes.number.def(140),
-    copy: propTypes.bool.def(true),
-    mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'),
+  export interface Props {
+    value?: string;
+    width?: string;
+    pageSize?: number;
+    copy?: boolean;
+    mode?: 'svg' | 'iconify';
+  }
+
+  const props = withDefaults(defineProps<Props>(), {
+    value: '',
+    width: '100%',
+    pageSize: 140,
+    copy: false,
+    mode: 'iconify',
   });
 
   const emit = defineEmits(['change', 'update:value']);
@@ -152,7 +159,8 @@
   }
 
   function handleSearchChange(e: Event) {
-    const value = e.target.value;
+    const value = (e.target as HTMLInputElement).value;
+
     if (!value) {
       setCurrentPage(1);
       currentList.value = icons;

+ 3 - 3
src/directives/clickOutside.ts

@@ -17,10 +17,10 @@ const nodeList: FlushList = new Map();
 let startClick: MouseEvent;
 
 if (!isServer) {
-  on(document, 'mousedown', (e: MouseEvent) => (startClick = e));
-  on(document, 'mouseup', (e: MouseEvent) => {
+  on(document, 'mousedown', (e: Event) => (startClick = e as MouseEvent));
+  on(document, 'mouseup', (e: Event) => {
     for (const { documentHandler } of nodeList.values()) {
-      documentHandler(e, startClick);
+      documentHandler(e as MouseEvent, startClick);
     }
   });
 }

+ 2 - 2
src/directives/repeatClick.ts

@@ -18,8 +18,8 @@ const repeatDirective: Directive = {
       interval = null;
     };
 
-    on(el, 'mousedown', (e: MouseEvent): void => {
-      if ((e as any).button !== 0) return;
+    on(el, 'mousedown', (e: Event): void => {
+      if ((e as MouseEvent).button !== 0) return;
       startTime = Date.now();
       once(document as any, 'mouseup', clear);
       interval && clearInterval(interval);

+ 2 - 2
src/directives/ripple/index.ts

@@ -28,9 +28,9 @@ const RippleDirective: Directive & RippleProto = {
     const background = bg || RippleDirective.background;
     const zIndex = RippleDirective.zIndex;
 
-    el.addEventListener(options.event, (event: EventType) => {
+    el.addEventListener(options.event, (event: Event) => {
       rippler({
-        event,
+        event: event as EventType,
         el,
         background,
         zIndex,

+ 2 - 2
src/locales/setupI18n.ts

@@ -1,5 +1,5 @@
 import type { App } from 'vue';
-import type { I18n, I18nOptions } from 'vue-i18n';
+import type { I18nOptions } from 'vue-i18n';
 
 import { createI18n } from 'vue-i18n';
 import { setHtmlPageLang, setLoadLocalePool } from './helper';
@@ -39,6 +39,6 @@ async function createI18nOptions(): Promise<I18nOptions> {
 // setup i18n instance with glob
 export async function setupI18n(app: App) {
   const options = await createI18nOptions();
-  i18n = createI18n(options) as I18n;
+  i18n = createI18n(options);
   app.use(i18n);
 }

+ 1 - 1
src/utils/domUtils.ts

@@ -158,7 +158,7 @@ export function off(
 export function once(el: HTMLElement, event: string, fn: EventListener): void {
   const listener = function (this: any, ...args: unknown[]) {
     if (fn) {
-      fn.apply(this, args);
+      fn.apply(this, args as [evt: Event]);
     }
     off(el, event, listener);
   };

+ 2 - 2
src/utils/propTypes.ts

@@ -20,13 +20,13 @@ const newPropTypes = createTypes({
 // 从 vue-types v5.0 开始,extend()方法已经废弃,当前已改为官方推荐的ES6+方法 https://dwightjack.github.io/vue-types/advanced/extending-vue-types.html#the-extend-method
 class propTypes extends newPropTypes {
   // a native-like validator that supports the `.validable` method
-  static get style() {
+  static override get style() {
     return toValidableType('style', {
       type: [String, Object],
     });
   }
 
-  static get VNodeChild() {
+  static override get VNodeChild() {
     return toValidableType('VNodeChild', {
       type: undefined,
     });

+ 4 - 3
src/utils/props.ts

@@ -129,7 +129,7 @@ export function buildProp<
 
   return {
     type:
-      typeof type === 'object' && Object.getOwnPropertySymbols(type).includes(wrapperKey)
+      typeof type === 'object' && Object.getOwnPropertySymbols(type).includes(wrapperKey) && type
         ? type[wrapperKey]
         : type,
     required: !!required,
@@ -175,9 +175,10 @@ export const buildProps = <
       : never;
   };
 
-export const definePropType = <T>(val: any) => ({ [wrapperKey]: val } as PropWrapper<T>);
+export const definePropType = <T>(val: any) => ({ [wrapperKey]: val }) as PropWrapper<T>;
+
+export const keyOf = <T extends object>(arr: T) => Object.keys(arr) as Array<keyof T>;
 
-export const keyOf = <T>(arr: T) => Object.keys(arr) as Array<keyof T>;
 export const mutable = <T extends readonly any[] | Record<string, unknown>>(val: T) =>
   val as Mutable<typeof val>;
 

+ 27 - 67
src/views/form-design/components/VFormDesign/components/FormItemProps.vue

@@ -61,8 +61,8 @@
     </div>
   </div>
 </template>
-<script lang="ts">
-  import { computed, defineComponent, watch } from 'vue';
+<script lang="ts" setup name="FormItemProps">
+  import { computed, watch } from 'vue';
   import {
     baseFormItemControlAttrs,
     baseFormItemProps,
@@ -70,76 +70,36 @@
     advanceFormItemColProps,
   } from '../../VFormDesign/config/formItemPropsConfig';
 
-  import {
-    Empty,
-    Input,
-    Form,
-    FormItem,
-    Switch,
-    Checkbox,
-    Select,
-    Slider,
-    Col,
-    RadioGroup,
-  } from 'ant-design-vue';
+  import { Empty, Input, Form, FormItem, Switch, Checkbox, Col } from 'ant-design-vue';
   import RuleProps from './RuleProps.vue';
   import { useFormDesignState } from '../../../hooks/useFormDesignState';
   import { isArray } from 'lodash-es';
 
-  export default defineComponent({
-    name: 'FormItemProps',
-    components: {
-      RuleProps,
-      Empty,
-      Input,
-      Form,
-      FormItem,
-      Switch,
-      Checkbox,
-      Select,
-      Slider,
-      Col,
-      RadioGroup,
-    },
-    // props: {} as PropsOptions,
-
-    setup() {
-      const { formConfig } = useFormDesignState();
+  const { formConfig } = useFormDesignState();
 
-      watch(
-        () => formConfig.value,
-        () => {
-          if (formConfig.value.currentItem) {
-            formConfig.value.currentItem.itemProps = formConfig.value.currentItem.itemProps || {};
-            formConfig.value.currentItem.itemProps.labelCol =
-              formConfig.value.currentItem.itemProps.labelCol || {};
-            formConfig.value.currentItem.itemProps.wrapperCol =
-              formConfig.value.currentItem.itemProps.wrapperCol || {};
-          }
-        },
-        { deep: true, immediate: true },
-      );
-      const showProps = (exclude: string[] | undefined) => {
-        if (!exclude) {
-          return true;
-        }
-        return isArray(exclude) ? !exclude.includes(formConfig.value.currentItem!.component) : true;
-      };
-
-      const controlPropsList = computed(() => {
-        return baseFormItemControlAttrs.filter((item) => {
-          return showProps(item.exclude);
-        });
-      });
-
-      return {
-        baseFormItemProps,
-        advanceFormItemProps,
-        advanceFormItemColProps,
-        formConfig,
-        controlPropsList,
-        showProps,
-      };
+  watch(
+    () => formConfig.value,
+    () => {
+      if (formConfig.value.currentItem) {
+        formConfig.value.currentItem.itemProps = formConfig.value.currentItem.itemProps || {};
+        formConfig.value.currentItem.itemProps.labelCol =
+          formConfig.value.currentItem.itemProps.labelCol || {};
+        formConfig.value.currentItem.itemProps.wrapperCol =
+          formConfig.value.currentItem.itemProps.wrapperCol || {};
+      }
     },
+    { deep: true, immediate: true },
+  );
+  const showProps = (exclude: string[] | undefined) => {
+    if (!exclude) {
+      return true;
+    }
+    return isArray(exclude) ? !exclude.includes(formConfig.value.currentItem!.component) : true;
+  };
+
+  const controlPropsList = computed(() => {
+    return baseFormItemControlAttrs.filter((item) => {
+      return showProps(item.exclude);
+    });
   });
 </script>

+ 19 - 30
src/views/form-design/components/VFormDesign/components/FormProps.vue

@@ -42,10 +42,10 @@
       </FormItem>
       <div v-if="formConfig.labelLayout === 'Grid'">
         <FormItem label="labelCol">
-          <Slider v-model:value="formConfig.labelCol!.span" :max="24" />
+          <Slider v-model:value="sliderSpan" :max="24" />
         </FormItem>
         <FormItem label="wrapperCol">
-          <Slider v-model:value="formConfig.wrapperCol!.span" :max="24" />
+          <Slider v-model:value="sliderSpan" :max="24" />
         </FormItem>
 
         <FormItem label="标签对齐">
@@ -75,8 +75,8 @@
     </Form>
   </div>
 </template>
-<script lang="ts">
-  import { defineComponent } from 'vue';
+<script lang="ts" setup name="FormProps">
+  import { computed } from 'vue';
   import { useFormDesignState } from '../../../hooks/useFormDesignState';
   import {
     InputNumber,
@@ -86,36 +86,25 @@
     RadioChangeEvent,
     Form,
     FormItem,
-    Radio,
   } from 'ant-design-vue';
 
-  export default defineComponent({
-    name: 'FormProps',
-    components: {
-      InputNumber,
-      Slider,
-      Checkbox,
-      RadioGroup: Radio.Group,
-      RadioButton: Radio.Button,
-      Form,
-      FormItem,
-      Col,
-    },
-    setup() {
-      const { formConfig } = useFormDesignState();
+  const { formConfig } = useFormDesignState();
 
-      formConfig.value = formConfig.value || {
-        labelCol: { span: 24 },
-        wrapperCol: { span: 24 },
-      };
+  formConfig.value = formConfig.value || {
+    labelCol: { span: 24 },
+    wrapperCol: { span: 24 },
+  };
 
-      const lableLayoutChange = (e: RadioChangeEvent) => {
-        if (e.target.value === 'Grid') {
-          formConfig.value.layout = 'horizontal';
-        }
-      };
+  const lableLayoutChange = (e: RadioChangeEvent) => {
+    if (e.target.value === 'Grid') {
+      formConfig.value.layout = 'horizontal';
+    }
+  };
 
-      return { formConfig, lableLayoutChange };
-    },
+  const sliderSpan = computed(() => {
+    if (formConfig.value.labelLayout) {
+      return Number(formConfig.value.labelCol!.span);
+    }
+    return 0;
   });
 </script>

+ 2 - 2
src/views/form-design/components/VFormDesign/modules/CollapseItem.vue

@@ -31,7 +31,7 @@
   </div>
 </template>
 <script lang="ts">
-  import { defineComponent, reactive } from 'vue';
+  import { defineComponent, reactive, PropType } from 'vue';
   import { IVFormComponent } from '../../../typings/v-form-component';
   import draggable from 'vuedraggable';
   import Icon from '@/components/Icon/Icon.vue';
@@ -42,7 +42,7 @@
     components: { draggable, Icon },
     props: {
       list: {
-        type: [Array],
+        type: [Array] as PropType<IVFormComponent[]>,
         default: () => [],
       },
       handleListPush: {

+ 16 - 19
src/views/form-design/typings/v-form-component.ts

@@ -8,8 +8,8 @@ import { SelectValue } from 'ant-design-vue/lib/select';
 import { validateOptions } from 'ant-design-vue/lib/form/useForm';
 import { RuleError } from 'ant-design-vue/lib/form/interface';
 import { FormItem } from '/@/components/Form';
+import { FormLayout, FormProps } from 'ant-design-vue/lib/form/Form';
 
-type LayoutType = 'horizontal' | 'vertical' | 'inline';
 type labelLayout = 'flex' | 'Grid';
 export type PropsTabKey = 1 | 2 | 3;
 type ColSpanType = number | string;
@@ -75,28 +75,25 @@ declare type namesType = string | string[];
 /**
  * 表单配置
  */
-export interface IFormConfig {
-  // 表单项配置列表
-  // schemas: IVFormComponent[];
-  // 表单配置
-  // config: {
-  layout?: LayoutType;
+export type PickAntFormConfig = Pick<
+  FormProps,
+  | 'layout'
+  | 'size'
+  | 'colon'
+  | 'labelAlign'
+  | 'disabled'
+  | 'labelCol'
+  | 'wrapperCol'
+  | 'hideRequiredMark'
+>;
+
+// 使用extends 而不使用 &联结 是为了避免 type:check指令类型重载错误
+export interface IFormConfig extends PickAntFormConfig {
   labelLayout?: labelLayout;
   labelWidth?: number;
-  labelCol?: Partial<IACol>;
-  wrapperCol?: Partial<IACol>;
-  hideRequiredMark?: boolean;
-  // Whether to disable
   schemas: IVFormComponent[];
-  disabled?: boolean;
-  labelAlign?: 'left' | 'right';
-  // Internal component size of the form
-  size?: 'default' | 'small' | 'large';
-  // };
-  // 当前选中项
   currentItem?: IVFormComponent;
   activeKey?: PropsTabKey;
-  colon?: boolean;
 }
 
 export interface AForm {
@@ -118,7 +115,7 @@ export interface AForm {
    * @default 'horizontal'
    * @type string
    */
-  layout: 'horizontal' | 'inline' | 'vertical';
+  layout: FormLayout;
 
   /**
    * The layout for input controls, same as labelCol

+ 7 - 3
src/views/sys/login/useLogin.ts

@@ -1,5 +1,9 @@
-import type { ValidationRule, FormInstance } from 'ant-design-vue/lib/form/Form';
-import type { RuleObject, NamePath } from 'ant-design-vue/lib/form/interface';
+import type { FormInstance } from 'ant-design-vue/lib/form/Form';
+import type {
+  RuleObject,
+  NamePath,
+  Rule as ValidationRule,
+} from 'ant-design-vue/lib/form/interface';
 import { ref, computed, unref, Ref } from 'vue';
 import { useI18n } from '/@/hooks/web/useI18n';
 
@@ -115,7 +119,7 @@ export function useFormRules(formData?: Recordable) {
   return { getFormRules };
 }
 
-function createRule(message: string) {
+function createRule(message: string): ValidationRule[] {
   return [
     {
       required: true,