refactor: ♻️ 字典重构和翻译完成

This commit is contained in:
ray
2024-10-05 23:45:34 +08:00
parent 33654c51bb
commit fa05379162
9 changed files with 167 additions and 32 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "vue3-element-admin", "name": "vue3-element-admin",
"version": "2.15.0", "version": "2.16.0",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {

View File

@@ -154,4 +154,9 @@ export interface DictDataForm {
* 字典排序 * 字典排序
*/ */
sort?: number; sort?: number;
/**
* 标签类型
*/
tagType: "success" | "warning" | "info" | "primary" | "danger" | undefined;
} }

View File

@@ -0,0 +1,52 @@
<template>
<template v-if="tag">
<el-tag :type="tag">{{ label }}</el-tag>
</template>
<template v-else>
<span>{{ label }}</span>
</template>
</template>
<script setup lang="ts">
import DictDataAPI from "@/api/dict-data";
import Cache from "@/utils/cache";
const props = defineProps({
dictCode: String,
value: [String, Number],
});
const label = ref("");
const tag = ref<
"success" | "warning" | "info" | "primary" | "danger" | undefined
>();
const dictCache = new Cache("dict_");
const getLabelAndTagByValue = async (dictCode: string, value: any) => {
let dictData = dictCache.getCache(dictCode);
if (!dictData) {
dictData = await DictDataAPI.getOptions(dictCode);
dictCache.setCache(dictCode, dictData, 3 * 60 * 1000); // 缓存 3 分钟
}
const dictEntry = dictData.find((item: any) => item.value == value);
return {
label: dictEntry ? dictEntry.label : "",
tag: dictEntry ? dictEntry.tag : undefined,
};
};
// 监听 props 的变化,获取并更新 label 和 tag
const fetchLabelAndTag = async () => {
const result = await getLabelAndTagByValue(
props.dictCode as string,
props.value
);
label.value = result.label;
tag.value = result.tag;
};
onMounted(fetchLabelAndTag);
watch(() => props.value, fetchLabelAndTag);
</script>

View File

@@ -14,6 +14,7 @@ declare module "vue" {
CopyButton: (typeof import("./../components/CopyButton/index.vue"))["default"]; CopyButton: (typeof import("./../components/CopyButton/index.vue"))["default"];
CURD: (typeof import("./../components/CURD/index.vue"))["default"]; CURD: (typeof import("./../components/CURD/index.vue"))["default"];
Dictionary: (typeof import("./../components/Dictionary/index.vue"))["default"]; Dictionary: (typeof import("./../components/Dictionary/index.vue"))["default"];
DictLabel: (typeof import("./../components/Dictionary/DictLabel.vue"))["default"];
ElBacktop: (typeof import("element-plus/es"))["ElBacktop"]; ElBacktop: (typeof import("element-plus/es"))["ElBacktop"];
ElBreadcrumb: (typeof import("element-plus/es"))["ElBreadcrumb"]; ElBreadcrumb: (typeof import("element-plus/es"))["ElBreadcrumb"];
ElBreadcrumbItem: (typeof import("element-plus/es"))["ElBreadcrumbItem"]; ElBreadcrumbItem: (typeof import("element-plus/es"))["ElBreadcrumbItem"];

View File

@@ -81,7 +81,7 @@ declare global {
} }
/** /**
* 组件数据源 * 下拉选项数据类型
*/ */
interface OptionType { interface OptionType {
/** 值 */ /** 值 */

79
src/utils/cache.ts Normal file
View File

@@ -0,0 +1,79 @@
const DEFAULT_CACHE_EXPIRY_TIME = 5 * 60 * 1000; // 默认缓存有效期为5分钟
/**
* 通用缓存工具类
*/
class Cache {
private cachePrefix: string;
constructor(prefix: string = "cache_") {
this.cachePrefix = prefix;
}
/**
* 设置缓存
*
* @param key 缓存的键
* @param data 缓存的数据
* @param expiryTime 缓存有效期毫秒默认5分钟
*/
setCache(
key: string,
data: any,
expiryTime: number = DEFAULT_CACHE_EXPIRY_TIME
) {
const expiryTimestamp = new Date().getTime() + expiryTime;
const cacheKey = this.cachePrefix + key;
const cacheData = { data, expiryTimestamp };
localStorage.setItem(cacheKey, JSON.stringify(cacheData));
}
/**
* 获取缓存
*
* @param key 缓存的键
* @returns 如果缓存有效则返回缓存的数据,否则返回 null
*/
getCache(key: string) {
const cacheKey = this.cachePrefix + key;
const cached = localStorage.getItem(cacheKey);
if (cached) {
const { data, expiryTimestamp } = JSON.parse(cached);
const now = new Date().getTime();
// 如果缓存未过期,返回数据
if (now < expiryTimestamp) {
return data;
} else {
// 如果缓存过期,移除缓存
localStorage.removeItem(cacheKey);
}
}
return null;
}
/**
* 移除缓存
*
* @param key 缓存的键
*/
removeCache(key: string) {
const cacheKey = this.cachePrefix + key;
localStorage.removeItem(cacheKey);
}
/**
* 清空当前前缀下的所有缓存
*/
clearCache() {
for (const key in localStorage) {
if (key.startsWith(this.cachePrefix)) {
localStorage.removeItem(key);
}
}
}
}
export default Cache;

View File

@@ -102,7 +102,7 @@
<el-dialog <el-dialog
v-model="dialog.visible" v-model="dialog.visible"
:title="dialog.title" :title="dialog.title"
width="500px" width="800px"
@close="handleCloseDialog" @close="handleCloseDialog"
> >
<el-form <el-form
@@ -124,13 +124,29 @@
<el-radio :value="0">禁用</el-radio> <el-radio :value="0">禁用</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="排序"> <el-form-item label="排序">
<el-input-number <el-input-number
v-model="formData.sort" v-model="formData.sort"
controls-position="right" controls-position="right"
/> />
</el-form-item> </el-form-item>
<el-form-item label="标签类型">
<el-tag
v-if="formData.tagType"
:type="formData.tagType"
class="mb-2"
>
{{ formData.label }}
</el-tag>
<el-radio-group v-model="formData.tagType">
<el-radio value="success" border size="small">success</el-radio>
<el-radio value="warning" border size="small">warning</el-radio>
<el-radio value="info" border size="small">info</el-radio>
<el-radio value="primary" border size="small">primary</el-radio>
<el-radio value="danger" border size="small">danger</el-radio>
<el-radio value="" border size="small">清空</el-radio>
</el-radio-group>
</el-form-item>
</el-card> </el-card>
</el-form> </el-form>

View File

@@ -77,15 +77,9 @@
prop="title" prop="title"
min-width="150" min-width="150"
/> />
<el-table-column <el-table-column align="center" label="通知类型" min-width="150">
align="center"
label="通知类型"
prop="typeLabel"
min-width="150"
>
<template #default="scope"> <template #default="scope">
<el-tag v-if="scope.row.type == 2" type="warning">系统通知</el-tag> <DictLabel :dictCode="'notice_type'" :value="scope.row.type" />
<el-tag v-if="scope.row.type == 1" type="success">通知消息</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@@ -94,17 +88,9 @@
prop="publisherName" prop="publisherName"
min-width="100" min-width="100"
/> />
<el-table-column <el-table-column align="center" label="通知等级" min-width="100">
align="center"
key="level"
label="通知等级"
prop="level"
min-width="100"
>
<template #default="scope"> <template #default="scope">
<el-tag v-if="scope.row.level == 'L'" type="danger"></el-tag> <DictLabel :dictCode="'notice_level'" :value="scope.row.level" />
<el-tag v-if="scope.row.level == 'M'" type="success"></el-tag>
<el-tag v-if="scope.row.level == 'H'" type="warning"></el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column

View File

@@ -38,12 +38,11 @@
prop="title" prop="title"
min-width="150" min-width="150"
/> />
<el-table-column <el-table-column align="center" label="通知类型" min-width="150">
align="center" <template #default="scope">
label="通知类型" <DictLabel :dictCode="'notice_type'" :value="scope.row.type" />
prop="typeLabel" </template>
min-width="150" </el-table-column>
/>
<el-table-column <el-table-column
align="center" align="center"
label="发布人" label="发布人"
@@ -52,10 +51,7 @@
/> />
<el-table-column align="center" label="通知等级" min-width="100"> <el-table-column align="center" label="通知等级" min-width="100">
<template #default="scope"> <template #default="scope">
<!-- 翻译字典 字典code 为level显示不同的tag和label --> <DictLabel :dictCode="'notice_level'" :value="scope.row.type" />
<el-tag v-if="scope.row.level == 'L'" type="danger"></el-tag>
<el-tag v-if="scope.row.level == 'M'" type="success"></el-tag>
<el-tag v-if="scope.row.level == 'H'" type="warning"></el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column