Преглед на файлове

perf: remove optional chain

vben преди 4 години
родител
ревизия
e034d1bacc

+ 12 - 0
CHANGELOG.zh_CN.md

@@ -1,9 +1,21 @@
 ## Wip
 
+### ✨ Features
+
+- 面包屑支持显示图标
+- 新增 tinymce 富文本组件
+
+### 🎫 Chores
+
+- 删除代码内的可选链语法
+
 ### 🐛 Bug Fixes
 
 - 修复抽屉组件自动高度及显示 footer 显示问题
 - 修复表单查询后重置回默认值
+- 修复菜单没有子节点时显示折叠的问题
+- 修复面包屑显示样式问题
+- 修复 modal 在 destroyOnClose=true 时多次打开拖拽失效
 
 # 2.0.0-rc.4 (2020-10-21)
 

+ 2 - 0
src/components/Authority/index.ts

@@ -0,0 +1,2 @@
+import Authority from './src/index.vue';
+export default Authority;

+ 0 - 61
src/components/Authority/index.tsx

@@ -1,61 +0,0 @@
-import { defineComponent, PropType, computed, unref } from 'vue';
-
-import { PermissionModeEnum } from '/@/enums/appEnum';
-import { RoleEnum } from '/@/enums/roleEnum';
-import { usePermission } from '/@/hooks/web/usePermission';
-import { appStore } from '/@/store/modules/app';
-import { getSlot } from '/@/utils/helper/tsxHelper';
-
-export default defineComponent({
-  name: 'Authority',
-  props: {
-    // 指定角色可见
-    value: {
-      type: [Number, Array, String] as PropType<RoleEnum | RoleEnum[]>,
-      default: '',
-    },
-  },
-  setup(props, { slots }) {
-    const getModeRef = computed(() => {
-      return appStore.getProjectConfig.permissionMode;
-    });
-
-    /**
-     * 渲染角色按钮
-     */
-    function renderRoleAuth() {
-      const { value } = props;
-      if (!value) {
-        return getSlot(slots);
-      }
-      const { hasPermission } = usePermission();
-      return hasPermission(value) ? getSlot(slots) : null;
-    }
-
-    /**
-     * 渲染编码按钮
-     * 这里只判断是否包含,具体实现可以根据项目自行写逻辑
-     */
-    function renderCodeAuth() {
-      const { value } = props;
-      if (!value) {
-        return getSlot(slots);
-      }
-      const { hasPermission } = usePermission();
-      return hasPermission(value) ? getSlot(slots) : null;
-    }
-
-    return () => {
-      const mode = unref(getModeRef);
-      // 基于角色渲染
-      if (mode === PermissionModeEnum.ROLE) {
-        return renderRoleAuth();
-      }
-      // 基于后台编码渲染
-      if (mode === PermissionModeEnum.BACK) {
-        return renderCodeAuth();
-      }
-      return getSlot(slots);
-    };
-  },
-});

+ 65 - 0
src/components/Authority/src/index.vue

@@ -0,0 +1,65 @@
+<script lang="ts">
+  import { defineComponent, PropType, computed, unref } from 'vue';
+
+  import { PermissionModeEnum } from '/@/enums/appEnum';
+  import { RoleEnum } from '/@/enums/roleEnum';
+  import { usePermission } from '/@/hooks/web/usePermission';
+  import { appStore } from '/@/store/modules/app';
+  import { getSlot } from '/@/utils/helper/tsxHelper';
+
+  export default defineComponent({
+    name: 'Authority',
+    props: {
+      // 指定角色可见
+      value: {
+        type: [Number, Array, String] as PropType<RoleEnum | RoleEnum[]>,
+        default: '',
+      },
+    },
+    setup(props, { slots }) {
+      const getModeRef = computed(() => {
+        return appStore.getProjectConfig.permissionMode;
+      });
+
+      /**
+       * 渲染角色按钮
+       */
+      function renderRoleAuth() {
+        const { value } = props;
+        if (!value) {
+          return getSlot(slots);
+        }
+        const { hasPermission } = usePermission();
+        return hasPermission(value) ? getSlot(slots) : null;
+      }
+
+      /**
+       * 渲染编码按钮
+       * 这里只判断是否包含,具体实现可以根据项目自行写逻辑
+       */
+      function renderCodeAuth() {
+        const { value } = props;
+        if (!value) {
+          return getSlot(slots);
+        }
+        const { hasPermission } = usePermission();
+        return hasPermission(value) ? getSlot(slots) : null;
+      }
+
+      return () => {
+        const mode = unref(getModeRef);
+        // 基于角色渲染
+        if (mode === PermissionModeEnum.ROLE) {
+          return renderRoleAuth();
+        }
+
+        // 基于后台编码渲染
+        if (mode === PermissionModeEnum.BACK) {
+          return renderCodeAuth();
+        }
+
+        return getSlot(slots);
+      };
+    },
+  });
+</script>

+ 1 - 1
src/components/Basic/index.ts

@@ -1,3 +1,3 @@
 export { default as BasicArrow } from './src/BasicArrow.vue';
-export { default as BasicHelp } from './src/BasicHelp';
+export { default as BasicHelp } from './src/BasicHelp.vue';
 export { default as BasicTitle } from './src/BasicTitle.vue';

+ 0 - 19
src/components/Basic/src/BasicHelp.less

@@ -1,19 +0,0 @@
-@import (reference) '../../../design/index.less';
-
-.base-help {
-  display: inline-block;
-  margin-left: 6px;
-  font-size: 14px;
-  color: @text-color-help-dark;
-  cursor: pointer;
-
-  &:hover {
-    color: @primary-color;
-  }
-
-  &__wrap {
-    p {
-      margin-bottom: 0;
-    }
-  }
-}

+ 0 - 107
src/components/Basic/src/BasicHelp.tsx

@@ -1,107 +0,0 @@
-import type { PropType } from 'vue';
-
-import { Tooltip } from 'ant-design-vue';
-import { InfoCircleOutlined } from '@ant-design/icons-vue';
-import { defineComponent, computed, unref } from 'vue';
-
-import { getPopupContainer } from '/@/utils';
-
-import { isString, isArray } from '/@/utils/is';
-import { getSlot } from '/@/utils/helper/tsxHelper';
-import './BasicHelp.less';
-export default defineComponent({
-  name: 'BaseHelp',
-  props: {
-    // max-width
-    maxWidth: {
-      type: String as PropType<string>,
-      default: '600px',
-    },
-    // Whether to display the serial number
-    showIndex: {
-      type: Boolean as PropType<boolean>,
-      default: false,
-    },
-    // Text list
-    text: {
-      type: [Array, String] as PropType<string[] | string>,
-    },
-    // color
-    color: {
-      type: String as PropType<string>,
-      default: '#ffffff',
-    },
-    fontSize: {
-      type: String as PropType<string>,
-      default: '14px',
-    },
-    absolute: {
-      type: Boolean as PropType<boolean>,
-      default: false,
-    },
-    // 定位
-    position: {
-      type: [Object] as PropType<any>,
-      default: () => ({
-        position: 'absolute',
-        left: 0,
-        bottom: 0,
-      }),
-    },
-  },
-  setup(props, { slots }) {
-    const getOverlayStyleRef = computed(() => {
-      return {
-        maxWidth: props.maxWidth,
-      };
-    });
-    const getWrapStyleRef = computed(() => {
-      return {
-        color: props.color,
-        fontSize: props.fontSize,
-      };
-    });
-    const getMainStyleRef = computed(() => {
-      return props.absolute ? props.position : {};
-    });
-
-    /**
-     * @description: 渲染内容
-     */
-    const renderTitle = () => {
-      const list = props.text;
-      if (isString(list)) {
-        return <p>{list}</p>;
-      }
-      if (isArray(list)) {
-        return list.map((item, index) => {
-          return (
-            <p key={item}>
-              {props.showIndex ? `${index + 1}. ` : ''}
-              {item}
-            </p>
-          );
-        });
-      }
-      return null;
-    };
-    return () => (
-      <Tooltip
-        title={(<div style={unref(getWrapStyleRef)}>{renderTitle()}</div>) as any}
-        placement="right"
-        overlayStyle={unref(getOverlayStyleRef)}
-        autoAdjustOverflow={true}
-        overlayClassName="base-help__wrap"
-        getPopupContainer={() => getPopupContainer()}
-      >
-        {{
-          default: () => (
-            <span class="base-help" style={unref(getMainStyleRef)}>
-              {getSlot(slots) || <InfoCircleOutlined />}
-            </span>
-          ),
-        }}
-      </Tooltip>
-    );
-  },
-});

+ 137 - 0
src/components/Basic/src/BasicHelp.vue

@@ -0,0 +1,137 @@
+<script lang="ts">
+  import type { PropType } from 'vue';
+
+  import { Tooltip } from 'ant-design-vue';
+  import { InfoCircleOutlined } from '@ant-design/icons-vue';
+  import { defineComponent, computed, unref, h } from 'vue';
+
+  import { getPopupContainer } from '/@/utils';
+
+  import { isString, isArray } from '/@/utils/is';
+  import { getSlot } from '/@/utils/helper/tsxHelper';
+  export default defineComponent({
+    name: 'BaseHelp',
+    components: { Tooltip },
+    props: {
+      // max-width
+      maxWidth: {
+        type: String as PropType<string>,
+        default: '600px',
+      },
+      // Whether to display the serial number
+      showIndex: {
+        type: Boolean as PropType<boolean>,
+        default: false,
+      },
+      // Text list
+      text: {
+        type: [Array, String] as PropType<string[] | string>,
+      },
+      // color
+      color: {
+        type: String as PropType<string>,
+        default: '#ffffff',
+      },
+      fontSize: {
+        type: String as PropType<string>,
+        default: '14px',
+      },
+      absolute: {
+        type: Boolean as PropType<boolean>,
+        default: false,
+      },
+      // 定位
+      position: {
+        type: [Object] as PropType<any>,
+        default: () => ({
+          position: 'absolute',
+          left: 0,
+          bottom: 0,
+        }),
+      },
+    },
+    setup(props, { slots }) {
+      const getOverlayStyleRef = computed(() => {
+        return {
+          maxWidth: props.maxWidth,
+        };
+      });
+      const getWrapStyleRef = computed(() => {
+        return {
+          color: props.color,
+          fontSize: props.fontSize,
+        };
+      });
+      const getMainStyleRef = computed(() => {
+        return props.absolute ? props.position : {};
+      });
+
+      /**
+       * @description: 渲染内容
+       */
+      const renderTitle = () => {
+        const list = props.text;
+        if (isString(list)) {
+          return h('p', list);
+        }
+        if (isArray(list)) {
+          return list.map((item, index) => {
+            return h('p', { key: item }, [props.showIndex ? `${index + 1}. ` : '', item]);
+          });
+        }
+        return null;
+      };
+      return () => {
+        return h(
+          Tooltip,
+          {
+            title: h(
+              'div',
+              {
+                style: unref(getWrapStyleRef),
+              },
+              [renderTitle()]
+            ) as any,
+            overlayClassName: 'base-help__wrap',
+            autoAdjustOverflow: true,
+            overlayStyle: unref(getOverlayStyleRef),
+            placement: 'right',
+            getPopupContainer: () => getPopupContainer(),
+          },
+          {
+            default: () =>
+              h(
+                'span',
+                {
+                  class: 'base-help',
+                  style: unref(getMainStyleRef),
+                },
+                getSlot(slots) || h(InfoCircleOutlined)
+              ),
+          }
+        );
+      };
+    },
+  });
+</script>
+<style lang="less">
+  @import (reference) '../../../design/index.less';
+
+  .base-help {
+    display: inline-block;
+    margin-left: 6px;
+    font-size: 14px;
+    color: @text-color-help-dark;
+    cursor: pointer;
+
+    &:hover {
+      color: @primary-color;
+    }
+
+    &__wrap {
+      p {
+        margin-bottom: 0;
+      }
+    }
+  }
+</style>

+ 0 - 66
src/components/Button/types.ts

@@ -1,66 +0,0 @@
-import { VNodeChild } from 'vue';
-
-export interface BasicButtonProps {
-  /**
-   * can be set to primary ghost dashed danger(added in 2.7) or omitted (meaning default)
-   * @default 'default'
-   * @type string
-   */
-  type?: 'primary' | 'danger' | 'dashed' | 'ghost' | 'default';
-
-  /**
-   * set the original html type of button
-   * @default 'button'
-   * @type string
-   */
-  htmlType?: 'button' | 'submit' | 'reset' | 'menu';
-
-  /**
-   * set the icon of button
-   * @type string
-   */
-  icon?: VNodeChild | JSX.Element;
-
-  /**
-   * can be set to circle or circle-outline or omitted
-   * @type string
-   */
-  shape?: 'circle' | 'circle-outline';
-
-  /**
-   * can be set to small large or omitted
-   * @default 'default'
-   * @type string
-   */
-  size?: 'small' | 'large' | 'default';
-
-  /**
-   * set the loading status of button
-   * @default false
-   * @type boolean | { delay: number }
-   */
-  loading?: boolean | { delay: number };
-
-  /**
-   * disabled state of button
-   * @default false
-   * @type boolean
-   */
-  disabled?: boolean;
-
-  /**
-   * make background transparent and invert text and border colors, added in 2.7
-   * @default false
-   * @type boolean
-   */
-  ghost?: boolean;
-
-  /**
-   * option to fit button width to its parent width
-   * @default false
-   * @type boolean
-   */
-  block?: boolean;
-
-  onClick?: (e?: Event) => void;
-}

+ 5 - 4
src/components/Table/src/components/TableAction.tsx

@@ -84,10 +84,11 @@ export default defineComponent({
       const { dropDownActions = [], actions } = props;
       return (
         <div class={prefixCls}>
-          {actions?.map((action, index) => {
-            return renderPopConfirm(action, index);
-          })}
-          {dropDownActions?.length && (
+          {actions &&
+            actions.map((action, index) => {
+              return renderPopConfirm(action, index);
+            })}
+          {dropDownActions && dropDownActions.length && (
             <Dropdown>
               {{
                 default: dropdownDefaultSLot,

+ 4 - 4
src/components/Table/src/components/renderEditableCell.tsx

@@ -45,8 +45,8 @@ const EditableCell = defineComponent({
     const isEditRef = ref(false);
     const currentValueRef = ref<string | boolean>(props.value);
 
-    function handleChange(e: ChangeEvent | string | boolean) {
-      if (Reflect.has((e as ChangeEvent)?.target, 'value')) {
+    function handleChange(e: any) {
+      if (e && e.target && Reflect.has(e.target, 'value')) {
         currentValueRef.value = (e as ChangeEvent).target.value;
       }
       if (isString(e) || isBoolean(e)) {
@@ -58,7 +58,7 @@ const EditableCell = defineComponent({
       isEditRef.value = true;
       nextTick(() => {
         const el = unref(elRef);
-        el?.focus();
+        el && el.focus();
       });
     }
 
@@ -84,7 +84,7 @@ const EditableCell = defineComponent({
     function onClickOutside() {
       const { component } = props;
 
-      if (component?.includes('Input')) {
+      if (component && component.includes('Input')) {
         handleCancel();
       }
     }

+ 1 - 1
src/components/Table/src/hooks/useDataSource.ts

@@ -89,7 +89,7 @@ export function useDataSource(
         pageParams = {};
       } else {
         const { current, pageSize } = unref(getPaginationRef) as PaginationProps;
-        pageParams[pageField] = opt?.page || current;
+        pageParams[pageField] = (opt && opt.page) || current;
         pageParams[sizeField] = pageSize;
       }
 

+ 3 - 3
src/components/Tinymce/src/Editor.vue

@@ -53,13 +53,12 @@
       });
 
       const initOptions = computed(() => {
-        const { height, menubar } = props;
+        const { height, options } = props;
         return {
           selector: `#${unref(tinymceId)}`,
           height: height,
           toolbar: toolbar,
-          theme: 'silver',
-          menubar: menubar,
+          menubar: 'file edit insert view format table',
           plugins: plugins,
           // 语言包
           language_url: 'resource/tinymce/langs/zh_CN.js',
@@ -70,6 +69,7 @@
           advlist_bullet_styles: 'square',
           advlist_number_styles: 'default',
           object_resizing: false,
+          ...options,
           setup: (editor: any) => {
             editorRef.value = editor;
             editor.on('init', (e: Event) => initSetup(e));

+ 3 - 3
src/components/Tinymce/src/props.ts

@@ -1,9 +1,9 @@
 import { PropType } from 'vue';
 
 export const basicProps = {
-  menubar: {
-    type: String as PropType<string>,
-    default: 'file edit insert view format table',
+  options: {
+    type: Object as PropType<any>,
+    default: {},
   },
   value: {
     type: String as PropType<string>,

+ 1 - 5
src/views/demo/editor/tinymce/index.vue

@@ -1,6 +1,5 @@
 <template>
-  <div class="flex p-4">
-    {{ value }}
+  <div class="p-4">
     <Tinymce v-model="value" @change="handleChange" width="100%" />
   </div>
 </template>
@@ -15,9 +14,6 @@
       function handleChange(value: string) {
         console.log(value);
       }
-      // setTimeout(() => {
-      //   value.value = '1233';
-      // }, 5000);
       return { handleChange, value };
     },
   });

+ 0 - 1
vite.config.ts

@@ -8,7 +8,6 @@ import {
   // externals,
   cdnConf,
 } from './build/config/vite/cdn';
-
 import { createProxy } from './build/config/vite/proxy';
 import { createMockServer } from 'vite-plugin-mock';
 import PurgeIcons from 'vite-plugin-purge-icons';