Skip to content

FEATURE: V5版本相对于V2版本缺少了很多组件,如果我想实现应该怎么实现呢 #6320

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
3 tasks done
YANG18642029437 opened this issue Jun 1, 2025 · 1 comment

Comments

@YANG18642029437
Copy link

Version

Vben Admin V5

Description

我现在项目中要使用 Description,和 QrCode 组件
Image

Proposed Solution

Alternatives Considered

No response

Additional Context

No response

Validations

  • Read the docs
  • Ensure the code is up to date. (Some issues have been fixed in the latest version)
  • I have searched the existing issues and checked that my issue does not duplicate any existing issues.
@YANG18642029437
Copy link
Author

我自己模仿 v2 写了一个 Descriptions 有兴趣的可以看一下

<script lang="tsx">
import type { CSSProperties, PropType } from 'vue';

import type { Recordable } from '@vben/types';

import type { DescItem } from './typing';

import { defineComponent, getCurrentInstance, h, ref, toRefs } from 'vue';

import { get, isFunction } from '@vben/utils';

import { Descriptions } from 'ant-design-vue';

const componentProps = {
  schema: {
    type: Array as PropType<DescItem[]>,
    default: () => [],
  },
  data: { type: Object },
};

export default defineComponent({
  name: 'Description',
  props: componentProps,
  emits: ['register'],
  setup: (props: any, { attrs, expose, slots }) => {
    const placeholder = props?.placeholder || attrs?.placeholder;
    // 透传组件暴露的方法
    const innerRef = ref();
    const publicApi: Recordable<any> = {};
    expose(publicApi);
    const instance = getCurrentInstance();
    instance?.proxy?.$nextTick(() => {
      for (const key in innerRef.value) {
        if (typeof innerRef.value[key] === 'function') {
          publicApi[key] = innerRef.value[key];
        }
      }
    });

    function renderItem() {
      const { schema, data } = props;
      return schema
        .map((item: any) => {
          const { render, field, span, show, contentMinWidth } = item;

          if (show && isFunction(show) && !show(data)) {
            return null;
          }

          const getContent = () => {
            const _data = data;
            if (!_data) {
              return null;
            }
            const getField = get(_data, field);
            // eslint-disable-next-line
            if (getField && !toRefs(_data).hasOwnProperty(field)) {
              return isFunction(render) ? render('', _data) : '';
            }
            return isFunction(render)
              ? render(getField, _data)
              : (getField ?? '');
          };

          const width = contentMinWidth;
          return (
            <Descriptions.Item
              key={field}
              label={renderLabel(item)}
              span={span}
            >
              {() => {
                if (!contentMinWidth) {
                  return getContent();
                }
                const style: CSSProperties = {
                  minWidth: `${width}px`,
                };
                return <div style={style}>{getContent()}</div>;
              }}
            </Descriptions.Item>
          );
        })
        .filter((item: any) => !!item);
    }

    function renderLabel({ label, labelMinWidth, labelStyle }: DescItem) {
      if (!labelStyle && !labelMinWidth) {
        return label;
      }

      const labelStyles: CSSProperties = {
        ...labelStyle,
        minWidth: `${labelMinWidth}px `,
      };
      return <div style={labelStyles}>{label}</div>;
    }

    return () =>
      h(
        Descriptions,
        {
          ...componentProps,
          placeholder,
          ...props,
          ...attrs,
          ref: innerRef,
        },
        {
          ...slots,
          default: () => {
            return renderItem();
          },
        },
      );
  },
});
</script>

TS

import type { DescriptionsProps } from 'ant-design-vue/es/descriptions';

import type { CSSProperties, VNode } from 'vue';

export interface DescItem {
  labelMinWidth?: number;
  contentMinWidth?: number;
  labelStyle?: CSSProperties;
  field: string;
  label: Element | string | VNode;
  // Merge column
  span?: number;
  show?: (...arg: any) => boolean;
  // render
  render?: (
    val: any,
    data: Record<string, any>,
  ) => Element | Element | number | string | undefined | VNode;
}

export interface DescriptionProps extends DescriptionsProps {
  /**
   * item configuration
   * @type DescItem
   */
  schema: DescItem[];
  /**
   * 数据
   * @type object
   */
  data: Record<string, any>;
}

export interface DescInstance {
  setDescProps(descProps: Partial<DescriptionProps>): void;
}

export type Register = (descInstance: DescInstance) => void;

/**
 * @description:
 */
export type UseDescReturnType = [Register, DescInstance];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant