feat(dict): 字典数据支持标签样式
- src/api/dict.ts: 字典数据补 tagType 字段,历史单字母值归一为语义名 - src/subPages/work/dict/item/index.vue: 列表按标签样式渲染,表单新增标签类型选择 - src/subPages/work/dict/index.vue: 删除确认提示会同时删除字典数据 - src/subPages/work/dict/index.vue、dict/item/index.vue: 保存失败提示后端返回的错误信息
This commit is contained in:
1 parent
4402bf26bc
commit
c9dcda4fed
3 files changed
+85
-5
No files matched your search
+35
-3
@@ -2,6 +2,31 @@ import request from "@/utils/request";
|
||||
|
||||
const DICT_BASE_URL = "/api/v1/dicts";
|
||||
|
||||
/** 标签样式的语义名 */
|
||||
const TAG_TYPE_NAMES = ["primary", "success", "warning", "danger", "info"];
|
||||
|
||||
/** 历史单字母标签样式对应的语义名 */
|
||||
const LEGACY_TAG_TYPES: Record<string, string> = {
|
||||
P: "primary",
|
||||
S: "success",
|
||||
W: "warning",
|
||||
D: "danger",
|
||||
I: "info",
|
||||
};
|
||||
|
||||
/**
|
||||
* 归一标签样式,把历史单字母值转成语义名
|
||||
*
|
||||
* 无样式或无法识别时返回空串
|
||||
*/
|
||||
function normalizeTagType(tagType?: string): string {
|
||||
const name = String(tagType ?? "")
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
if (!name || name === "n" || name === "default") return "";
|
||||
return TAG_TYPE_NAMES.includes(name) ? name : (LEGACY_TAG_TYPES[name.toUpperCase()] ?? "");
|
||||
}
|
||||
|
||||
const DictAPI = {
|
||||
/** 获取字典类型分页数据 */
|
||||
getPage(queryParams: DictTypePageQuery) {
|
||||
@@ -56,7 +81,10 @@ const DictAPI = {
|
||||
url: `${DICT_BASE_URL}/${dictCode}/items`,
|
||||
method: "GET",
|
||||
data: queryParams,
|
||||
});
|
||||
}).then((data) => ({
|
||||
...data,
|
||||
list: (data.list ?? []).map((item) => ({ ...item, tagType: normalizeTagType(item.tagType) })),
|
||||
}));
|
||||
},
|
||||
|
||||
/** 获取字典数据表单数据 */
|
||||
@@ -64,7 +92,7 @@ const DictAPI = {
|
||||
return request<DictItemForm>({
|
||||
url: `${DICT_BASE_URL}/${dictCode}/items/${id}/form`,
|
||||
method: "GET",
|
||||
});
|
||||
}).then((data) => ({ ...data, tagType: normalizeTagType(data.tagType) }));
|
||||
},
|
||||
|
||||
/** 新增字典数据 */
|
||||
@@ -135,9 +163,11 @@ export interface DictItemForm {
|
||||
dictCode?: string;
|
||||
label?: string;
|
||||
value?: string;
|
||||
sort: number;
|
||||
sort?: number;
|
||||
status?: number;
|
||||
remark?: string;
|
||||
/** 标签样式(primary/success/warning/danger/info,空为无样式) */
|
||||
tagType?: string;
|
||||
}
|
||||
|
||||
/** 字典数据分页对象 */
|
||||
@@ -149,4 +179,6 @@ export interface DictItem {
|
||||
sort?: number;
|
||||
status?: number;
|
||||
remark?: string;
|
||||
/** 标签样式(primary/success/warning/danger/info,空为无样式) */
|
||||
tagType?: string;
|
||||
}
|
||||
@@ -104,6 +104,7 @@ import { useActionSheet, type ActionMenuOption } from "@/composables/useActionSh
|
||||
import { usePagedList } from "@/composables/usePagedList";
|
||||
import DictAPI, { type DictTypeForm, type DictTypePageQuery, type DictTypeItem } from "@/api/dict";
|
||||
import { hasPermission } from "@/utils/permission";
|
||||
import { getErrorMessage } from "@/utils/error";
|
||||
|
||||
definePage({
|
||||
name: "dict",
|
||||
@@ -182,6 +183,9 @@ function submitDictForm() {
|
||||
closeDictDialog();
|
||||
loadDictTypeList();
|
||||
})
|
||||
.catch((error) => {
|
||||
toast.error(getErrorMessage(error, "保存失败"));
|
||||
})
|
||||
.finally(() => {
|
||||
isSubmitting.value = false;
|
||||
});
|
||||
@@ -207,7 +211,7 @@ function showDictActions(item: DictTypeItem) {
|
||||
color: "var(--color-danger)",
|
||||
handler: () =>
|
||||
confirmAction({
|
||||
msg: `确定要删除字典「${item.name}」吗?`,
|
||||
msg: `删除字典「${item.name}」会同时删除其字典数据,确定继续吗?`,
|
||||
action: async () => {
|
||||
if (!item.id) return;
|
||||
await DictAPI.deleteByIds(String(item.id));
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
<view class="flex-start">
|
||||
<view class="flex-1">
|
||||
<view class="flex-start">
|
||||
<text class="font-bold text-32rpx">{{ item.label }}</text>
|
||||
<wd-tag v-if="tagComponentType(item.tagType)" :type="tagComponentType(item.tagType)">
|
||||
{{ item.label }}
|
||||
</wd-tag>
|
||||
<text v-else class="font-bold text-32rpx">{{ item.label }}</text>
|
||||
</view>
|
||||
<text class="text-24rpx color-text-secondary">
|
||||
字典值:{{ item.value }} · 排序:{{ item.sort }}
|
||||
@@ -58,6 +61,18 @@
|
||||
<wd-form-item prop="value" title="字典项值" required>
|
||||
<wd-input v-model="formData.value" placeholder="请输入字典项值" />
|
||||
</wd-form-item>
|
||||
<wd-form-item prop="tagType" title="标签类型">
|
||||
<wd-radio-group v-model="formData.tagType" size="small" type="button">
|
||||
<wd-radio value="">无</wd-radio>
|
||||
<wd-radio
|
||||
v-for="option in TAG_TYPE_OPTIONS"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>
|
||||
{{ option.label }}
|
||||
</wd-radio>
|
||||
</wd-radio-group>
|
||||
</wd-form-item>
|
||||
<wd-form-item prop="status" title="状态">
|
||||
<wd-switch v-model="formData.status" :active-value="1" :inactive-value="0" />
|
||||
</wd-form-item>
|
||||
@@ -108,6 +123,8 @@ import { useActionSheet, type ActionMenuOption } from "@/composables/useActionSh
|
||||
import { usePagedList } from "@/composables/usePagedList";
|
||||
import DictAPI, { type DictItemForm, type DictItemPageQuery, type DictItem } from "@/api/dict";
|
||||
import { hasPermission } from "@/utils/permission";
|
||||
import { getErrorMessage } from "@/utils/error";
|
||||
import type { TagType } from "@wot-ui/ui/components/wd-tag/types";
|
||||
|
||||
definePage({
|
||||
name: "dict-item",
|
||||
@@ -153,8 +170,32 @@ const initialFormData: DictItemForm = {
|
||||
sort: 1,
|
||||
status: 1,
|
||||
remark: undefined,
|
||||
tagType: "",
|
||||
};
|
||||
|
||||
/** 标签类型选项,值为后端存储的语义名 */
|
||||
const TAG_TYPE_OPTIONS = [
|
||||
{ value: "primary", label: "主要" },
|
||||
{ value: "success", label: "成功" },
|
||||
{ value: "info", label: "信息" },
|
||||
{ value: "warning", label: "警告" },
|
||||
{ value: "danger", label: "危险" },
|
||||
];
|
||||
|
||||
/** 语义名与 wd-tag 类型的对应关系,info 用默认样式呈现 */
|
||||
const TAG_COMPONENT_TYPES: Record<string, TagType> = {
|
||||
primary: "primary",
|
||||
success: "success",
|
||||
warning: "warning",
|
||||
danger: "danger",
|
||||
info: "default",
|
||||
};
|
||||
|
||||
/** 字典项标签在 wd-tag 上的呈现类型,无标签类型时返回空串 */
|
||||
function tagComponentType(tagType?: string): TagType | "" {
|
||||
return TAG_COMPONENT_TYPES[tagType ?? ""] ?? "";
|
||||
}
|
||||
|
||||
const formData = reactive<DictItemForm>({ ...initialFormData });
|
||||
|
||||
const rules = toFormSchema({
|
||||
@@ -202,6 +243,9 @@ function submitItemForm() {
|
||||
closeItemDialog();
|
||||
loadItemList();
|
||||
})
|
||||
.catch((error) => {
|
||||
toast.error(getErrorMessage(error, "保存失败"));
|
||||
})
|
||||
.finally(() => {
|
||||
isSubmitting.value = false;
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user