refactor: ♻️ 代码规范调整和已知问题修复

This commit is contained in:
Ray.Hao
2025-04-15 23:31:17 +08:00
parent f048376eb3
commit 4cc36629a8
13 changed files with 474 additions and 469 deletions

View File

@@ -1,18 +1,9 @@
<template>
<template v-if="Array.isArray(modelValue)">
<el-tag
v-for="(tag, index) in tagList"
:key="index"
:type="tag.tagType"
:size="tagSize"
class="me-1"
>
{{ tag.label }}
</el-tag>
<template v-if="tagType">
<el-tag :type="tagType" :size="tagSize">{{ label }}</el-tag>
</template>
<template v-else>
<el-tag v-if="tagType" :type="tagType" :size="tagSize">{{ label }}</el-tag>
<span v-else>{{ label }}</span>
<span>{{ label }}</span>
</template>
</template>
<script setup lang="ts">
@@ -20,20 +11,16 @@ import { useDictStore } from "@/store";
const props = defineProps({
code: String, // 字典编码
modelValue: [String, Number, Array], // 字典项的值
modelValue: [String, Number], // 字典项的值
size: {
type: String,
default: "default", // 标签大小
},
});
const label = ref("");
type TagType = "success" | "info" | "warning" | "danger" | "primary";
const tagType = ref<TagType | undefined>(undefined);
const tagType = ref<"success" | "warning" | "info" | "primary" | "danger" | undefined>(); // 标签类型
const tagSize = ref<"default" | "large" | "small">(props.size as "default" | "large" | "small"); // 标签大小
// 多个标签时使用
const tagList = ref<Array<{ label: string; tagType?: TagType }>>([]);
const dictStore = useDictStore();
/**
* 根据字典项的值获取对应的 label 和 tagType
@@ -49,27 +36,24 @@ const getLabelAndTagByValue = async (dictCode: string, value: any) => {
// 查找对应的字典项
const dictItem = dictItems.find((item) => item.value == value);
return {
label: dictItem?.label || String(value),
tagType: dictItem?.tagType as TagType,
label: dictItem?.label || "",
tagType: dictItem?.tagType,
};
};
/**
* 更新 label 和 tagType
*/
const updateLabelAndTag = async () => {
if (!props.code || props.modelValue === undefined || props.modelValue === null) return;
await dictStore.loadDictItems(props.code);
if (Array.isArray(props.modelValue)) {
const results = await Promise.all(
props.modelValue.map((val) => getLabelAndTagByValue(props.code!, val))
);
tagList.value = results;
} else {
const result = await getLabelAndTagByValue(props.code, props.modelValue);
label.value = result.label;
tagType.value = result.tagType as typeof tagType.value;
}
console.log("updateLabelAndTag", props.code, props.modelValue);
if (!props.code || props.modelValue === undefined) return;
const { label: newLabel, tagType: newTagType } = await getLabelAndTagByValue(
props.code,
props.modelValue
);
label.value = newLabel;
tagType.value = newTagType as typeof tagType.value;
};
watch([() => props.code, () => props.modelValue], updateLabelAndTag);
onMounted(updateLabelAndTag);

View File

@@ -1,11 +1,9 @@
<template>
<!-- Select / Select-Multiple -->
<el-select
v-if="['select', 'select-multiple'].includes(type)"
v-if="type === 'select'"
v-model="selectedValue"
:placeholder="placeholder"
:disabled="disabled"
:multiple="type === 'select-multiple'"
clearable
:style="style"
@change="handleChange"
@@ -18,7 +16,6 @@
/>
</el-select>
<!-- Radio -->
<el-radio-group
v-else-if="type === 'radio'"
v-model="selectedValue"
@@ -36,7 +33,6 @@
</el-radio>
</el-radio-group>
<!-- Checkbox -->
<el-checkbox-group
v-else-if="type === 'checkbox'"
v-model="selectedValue"
@@ -56,7 +52,6 @@
</template>
<script setup lang="ts">
import { ref, watch, onMounted } from "vue";
import { useDictStore } from "@/store";
const dictStore = useDictStore();
@@ -73,8 +68,7 @@ const props = defineProps({
type: {
type: String,
default: "select",
validator: (value: string) =>
["select", "select-multiple", "radio", "checkbox"].includes(value),
validator: (value: string) => ["select", "radio", "checkbox"].includes(value),
},
placeholder: {
type: String,
@@ -86,7 +80,11 @@ const props = defineProps({
},
style: {
type: Object,
default: () => ({ width: "300px" }),
default: () => {
return {
width: "300px",
};
},
},
});
@@ -94,29 +92,35 @@ const emit = defineEmits(["update:modelValue"]);
const options = ref<Array<{ label: string; value: string | number }>>([]);
// 动态初始化 selectedValue
const selectedValue = ref<any>(
["select-multiple", "checkbox"].includes(props.type)
? Array.isArray(props.modelValue)
typeof props.modelValue === "string" || typeof props.modelValue === "number"
? props.modelValue
: Array.isArray(props.modelValue)
? props.modelValue
: []
: (props.modelValue ?? undefined)
: undefined
);
// 同步 selectedValue 与 props.modelValue
// 监听 modelValue 和 options 的变化
watch(
() => props.modelValue,
(newValue) => {
if (["select-multiple", "checkbox"].includes(props.type)) {
selectedValue.value = Array.isArray(newValue) ? newValue : [];
[() => props.modelValue, () => options.value],
([newValue, newOptions]) => {
if (newOptions.length > 0 && newValue !== undefined) {
if (props.type === "checkbox") {
selectedValue.value = Array.isArray(newValue) ? newValue : [];
} else {
const matchedOption = newOptions.find(
(option) => String(option.value) === String(newValue)
);
selectedValue.value = matchedOption?.value;
}
} else {
selectedValue.value = newValue ?? undefined;
selectedValue.value = undefined;
}
},
{ immediate: true }
);
// selectedValue 改变时回传给父组件
// 监听 selectedValue 的变化并触发 update:modelValue
function handleChange(val: any) {
emit("update:modelValue", val);
}