feat: 字典(DictTag)支持fallback属性(未匹配到字典项时的回显)
This commit is contained in:
parent
253c9b5248
commit
808406ebce
@ -5,10 +5,12 @@
|
||||
- 流程表达式 follow后端更新
|
||||
- websocket功能(默认关闭)
|
||||
- useVbenForm 增加 TimeRangePicker(时间区间选择) 组件
|
||||
- 字典(DictTag)支持fallback属性(未匹配到字典项时的回显)
|
||||
|
||||
**REFACTOR**
|
||||
|
||||
- Modal/Drawer中使用VxeTable tooltip需要设置更高的z-index 防止被遮挡
|
||||
- 字典(DictTag)使用tsx写法重构
|
||||
|
||||
**OTHERS**
|
||||
|
||||
|
||||
@ -1,62 +1,134 @@
|
||||
<!-- eslint-disable eqeqeq -->
|
||||
<script setup lang="ts">
|
||||
<script lang="tsx">
|
||||
import type { PropType } from 'vue';
|
||||
|
||||
import type { DictFallback } from './type';
|
||||
|
||||
import type { DictData } from '#/api/system/dict/dict-data-model';
|
||||
|
||||
import { computed } from 'vue';
|
||||
import { computed, defineComponent, h } from 'vue';
|
||||
|
||||
import { Spin, Tag } from 'ant-design-vue';
|
||||
import { isFunction, isString } from 'lodash-es';
|
||||
|
||||
import { tagTypes } from './data';
|
||||
|
||||
interface Props {
|
||||
dicts: DictData[]; // dict数组
|
||||
value: number | string; // value
|
||||
}
|
||||
/**
|
||||
* 使用tsx重构原来的template写法
|
||||
* 在大量if的情况 tsx比template的v-if好用得多
|
||||
*/
|
||||
export default defineComponent({
|
||||
name: 'DictTag',
|
||||
props: {
|
||||
/**
|
||||
* 字典项options
|
||||
*/
|
||||
dicts: {
|
||||
required: false,
|
||||
type: Array as PropType<DictData[]>,
|
||||
default: () => [],
|
||||
},
|
||||
/**
|
||||
* 当前值
|
||||
*/
|
||||
value: {
|
||||
required: true,
|
||||
type: [Number, String],
|
||||
},
|
||||
/**
|
||||
* 未匹配到字典项的fallback
|
||||
*/
|
||||
fallback: {
|
||||
required: false,
|
||||
type: [String, Function] as PropType<DictFallback>,
|
||||
default: 'unknown',
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const color = computed<string>(() => {
|
||||
const current = props.dicts.find((item) => item.dictValue == props.value);
|
||||
const listClass = current?.listClass ?? '';
|
||||
// 是否为默认的颜色
|
||||
const isDefault = Reflect.has(tagTypes, listClass);
|
||||
// 判断是默认还是自定义颜色
|
||||
if (isDefault) {
|
||||
// 这里做了antd - element-plus的兼容
|
||||
return tagTypes[listClass]!.color;
|
||||
}
|
||||
return listClass;
|
||||
});
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
dicts: undefined,
|
||||
});
|
||||
const cssClass = computed<string>(() => {
|
||||
const current = props.dicts.find((item) => item.dictValue == props.value);
|
||||
return current?.cssClass ?? '';
|
||||
});
|
||||
|
||||
const color = computed<string>(() => {
|
||||
const current = props.dicts.find((item) => item.dictValue == props.value);
|
||||
const listClass = current?.listClass ?? '';
|
||||
// 是否为默认的颜色
|
||||
const isDefault = Reflect.has(tagTypes, listClass);
|
||||
// 判断是默认还是自定义颜色
|
||||
if (isDefault) {
|
||||
// 这里做了antd - element-plus的兼容
|
||||
return tagTypes[listClass]!.color;
|
||||
}
|
||||
return listClass;
|
||||
});
|
||||
/**
|
||||
* 返回null 走 fallback逻辑
|
||||
*/
|
||||
const label = computed<null | string>(() => {
|
||||
const current = props.dicts.find((item) => item.dictValue == props.value);
|
||||
return current?.dictLabel ?? null;
|
||||
});
|
||||
|
||||
const cssClass = computed<string>(() => {
|
||||
const current = props.dicts.find((item) => item.dictValue == props.value);
|
||||
return current?.cssClass ?? '';
|
||||
});
|
||||
const loading = computed(() => {
|
||||
return props.dicts?.length === 0;
|
||||
});
|
||||
|
||||
const label = computed<number | string>(() => {
|
||||
const current = props.dicts.find((item) => item.dictValue == props.value);
|
||||
return current?.dictLabel ?? 'unknown';
|
||||
});
|
||||
return {
|
||||
color,
|
||||
cssClass,
|
||||
label,
|
||||
loading,
|
||||
};
|
||||
},
|
||||
render() {
|
||||
const { color, cssClass, label, loading, fallback, value } = this;
|
||||
|
||||
const tagComponent = computed(() => (color.value ? Tag : 'div'));
|
||||
/**
|
||||
* 字典list为0 加载中
|
||||
*/
|
||||
if (loading) {
|
||||
return (
|
||||
<div>
|
||||
<Spin size="small" spinning />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const loading = computed(() => {
|
||||
return props.dicts?.length === 0;
|
||||
/**
|
||||
* 没有匹配到字典(label === null)的fallback
|
||||
* 可为string/Vnode
|
||||
*/
|
||||
if (label === null) {
|
||||
// VNode
|
||||
if (isFunction(fallback)) {
|
||||
return h(fallback(value));
|
||||
}
|
||||
// 默认显示 unknown 文案
|
||||
if (isString(fallback)) {
|
||||
return <div>{fallback}</div>;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 有color 属性 渲染Tag
|
||||
*/
|
||||
if (color) {
|
||||
return (
|
||||
<div>
|
||||
<Tag class={cssClass} color={color}>
|
||||
{label}
|
||||
</Tag>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div class={cssClass}>{label}</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<component
|
||||
v-if="!loading"
|
||||
:is="tagComponent"
|
||||
:class="cssClass"
|
||||
:color="color"
|
||||
>
|
||||
{{ label }}
|
||||
</component>
|
||||
<Spin v-else :spinning="true" size="small" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
5
apps/web-antd/src/components/dict/src/type.d.ts
vendored
Normal file
5
apps/web-antd/src/components/dict/src/type.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* fallback的渲染
|
||||
* 可返回 字符串/Vnode
|
||||
*/
|
||||
export type DictFallback = ((current: number | string) => VNode) | string;
|
||||
@ -1,6 +1,7 @@
|
||||
import type { Component as ComponentType } from 'vue';
|
||||
|
||||
import type { DictData } from '#/api/system/dict/dict-data-model';
|
||||
import type { DictFallback } from '#/components/dict/src/type';
|
||||
|
||||
import { h } from 'vue';
|
||||
|
||||
@ -149,16 +150,26 @@ export function renderDictTags(
|
||||
);
|
||||
}
|
||||
|
||||
export interface RenderDictOptions {
|
||||
fallback?: DictFallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示字典标签 一般是table使用
|
||||
* @param value 值
|
||||
* @param dictName dictName
|
||||
* @returns tag
|
||||
*/
|
||||
export function renderDict(value: number | string, dictName: string) {
|
||||
export function renderDict(
|
||||
value: number | string,
|
||||
dictName: string,
|
||||
options?: RenderDictOptions,
|
||||
) {
|
||||
const { fallback } = options ?? {};
|
||||
const dictInfo = getDictOptions(dictName);
|
||||
return renderDictTag(value, dictInfo);
|
||||
return <DictTag dicts={dictInfo} fallback={fallback} value={value}></DictTag>;
|
||||
}
|
||||
|
||||
export function renderIconSpan(
|
||||
icon: ComponentType,
|
||||
value: string,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user