feat(product): 新增产品管理模块与字典组件功能
- 新增产品管理相关路由和页面(dashboard、list、requirement、setting) - 实现产品基础信息编辑弹窗组件(base-info-dialog.vue) - 添加运行时字典功能(dict-select、dict-text、dict-tag组件) - 集成字典管理store和API调用 - 规范ID类型定义为string避免精度丢失问题 - 完善国际化资源文件支持中英文对照 - 新增对象上下文业务域入口页导航实现说明 - 添加Vue DevTools浮动入口注释说明 - 统一权限控制支持全局和对象作用域区分 - 规范分页查询参数类型定义与使用方式
This commit is contained in:
62
src/components/custom/dict-select.vue
Normal file
62
src/components/custom/dict-select.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { useDict } from '@/hooks/business/dict';
|
||||
|
||||
defineOptions({ name: 'DictSelect' });
|
||||
|
||||
interface Props {
|
||||
dictCode: string;
|
||||
placeholder?: string;
|
||||
disabled?: boolean;
|
||||
clearable?: boolean;
|
||||
filterable?: boolean;
|
||||
onlyEnabled?: boolean;
|
||||
multiple?: boolean;
|
||||
collapseTags?: boolean;
|
||||
collapseTagsTooltip?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
placeholder: '请选择',
|
||||
disabled: false,
|
||||
clearable: true,
|
||||
filterable: false,
|
||||
onlyEnabled: true,
|
||||
multiple: false,
|
||||
collapseTags: false,
|
||||
collapseTagsTooltip: false
|
||||
});
|
||||
|
||||
const model = defineModel<string | number | Array<string | number> | null | undefined>({
|
||||
default: undefined
|
||||
});
|
||||
|
||||
const { enabledDictData, dictData } = useDict(() => props.dictCode);
|
||||
|
||||
const dictOptions = computed(() => {
|
||||
const source = props.onlyEnabled ? enabledDictData.value : dictData.value;
|
||||
|
||||
return source.map(item => ({
|
||||
label: item.label,
|
||||
value: item.value
|
||||
}));
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElSelect
|
||||
v-model="model"
|
||||
class="w-full"
|
||||
:placeholder="props.placeholder"
|
||||
:disabled="props.disabled"
|
||||
:clearable="props.clearable"
|
||||
:filterable="props.filterable"
|
||||
:multiple="props.multiple"
|
||||
:collapse-tags="props.collapseTags"
|
||||
:collapse-tags-tooltip="props.collapseTagsTooltip"
|
||||
>
|
||||
<ElOption v-for="item in dictOptions" :key="item.value" :label="item.label" :value="item.value" />
|
||||
</ElSelect>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
48
src/components/custom/dict-tag.vue
Normal file
48
src/components/custom/dict-tag.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<script setup lang="ts">
|
||||
import DictText from './dict-text.vue';
|
||||
|
||||
defineOptions({ name: 'DictTag' });
|
||||
|
||||
type DictValue = string | number;
|
||||
type DictTagType = 'primary' | 'success' | 'info' | 'warning' | 'danger';
|
||||
type DictTagEffect = 'dark' | 'light' | 'plain';
|
||||
type DictTagSize = 'large' | 'default' | 'small';
|
||||
|
||||
interface Props {
|
||||
dictCode: string;
|
||||
value?: DictValue | DictValue[] | null;
|
||||
fallback?: string;
|
||||
separator?: string;
|
||||
onlyEnabled?: boolean;
|
||||
type?: DictTagType;
|
||||
effect?: DictTagEffect;
|
||||
size?: DictTagSize;
|
||||
round?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
value: null,
|
||||
fallback: '--',
|
||||
separator: ' / ',
|
||||
onlyEnabled: false,
|
||||
type: undefined,
|
||||
effect: 'light',
|
||||
size: 'default',
|
||||
round: false
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElTag :type="props.type" :effect="props.effect" :size="props.size" :round="props.round">
|
||||
<DictText
|
||||
:dict-code="props.dictCode"
|
||||
:value="props.value"
|
||||
:fallback="props.fallback"
|
||||
:separator="props.separator"
|
||||
:only-enabled="props.onlyEnabled"
|
||||
tag="span"
|
||||
/>
|
||||
</ElTag>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
53
src/components/custom/dict-text.vue
Normal file
53
src/components/custom/dict-text.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { useDict } from '@/hooks/business/dict';
|
||||
|
||||
defineOptions({
|
||||
name: 'DictText',
|
||||
inheritAttrs: false
|
||||
});
|
||||
|
||||
type DictValue = string | number;
|
||||
|
||||
interface Props {
|
||||
dictCode: string;
|
||||
value?: DictValue | DictValue[] | null;
|
||||
fallback?: string;
|
||||
separator?: string;
|
||||
onlyEnabled?: boolean;
|
||||
tag?: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
value: null,
|
||||
fallback: '--',
|
||||
separator: ' / ',
|
||||
onlyEnabled: false,
|
||||
tag: 'span'
|
||||
});
|
||||
|
||||
const { getLabel, getLabels } = useDict(() => props.dictCode);
|
||||
|
||||
const text = computed(() => {
|
||||
if (Array.isArray(props.value)) {
|
||||
return getLabels(props.value, {
|
||||
fallback: props.fallback,
|
||||
separator: props.separator,
|
||||
onlyEnabled: props.onlyEnabled
|
||||
});
|
||||
}
|
||||
|
||||
return getLabel(props.value, {
|
||||
fallback: props.fallback,
|
||||
onlyEnabled: props.onlyEnabled
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="props.tag" v-bind="$attrs">
|
||||
{{ text }}
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
Reference in New Issue
Block a user