feat: 添加缓存列表
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
import { http } from "@/utils/http";
|
import { http } from "@/utils/http";
|
||||||
import type {
|
import type {
|
||||||
|
CacheItem,
|
||||||
|
CacheList,
|
||||||
OperationLogInfo,
|
OperationLogInfo,
|
||||||
RedisMonitorInfo,
|
RedisMonitorInfo,
|
||||||
SystemMonitorInfo,
|
SystemMonitorInfo,
|
||||||
@@ -70,3 +72,38 @@ export const getSystemMonitorInfoAPI = () => {
|
|||||||
export const getCachedMonitorInfoAPI = () => {
|
export const getCachedMonitorInfoAPI = () => {
|
||||||
return http.request<RedisMonitorInfo>("get", "/api/cache/monitor");
|
return http.request<RedisMonitorInfo>("get", "/api/cache/monitor");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取缓存名称列表
|
||||||
|
*/
|
||||||
|
export const getCachedNamesAPI = () => {
|
||||||
|
return http.request<CacheList>("get", "/api/cache/names");
|
||||||
|
};
|
||||||
|
|
||||||
|
/**获取缓存键名列表 */
|
||||||
|
export const getCachedKeysAPI = (cacheName: string) => {
|
||||||
|
return http.request<string[]>("get", `/api/cache/keys/${cacheName}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**获取缓存详细信息 */
|
||||||
|
export const getCachedInfoAPI = (cacheName: string, cacheKey: string) => {
|
||||||
|
return http.request<CacheItem>(
|
||||||
|
"get",
|
||||||
|
`/api/cache/info/${cacheName}/${cacheKey}`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**通过键名删除缓存 */
|
||||||
|
export const deleteCachedAPI = (name: string) => {
|
||||||
|
return http.request<null>("delete", `/api/cache/cacheName/${name}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**通过键值删除缓存 */
|
||||||
|
export const deleteCachedKeyAPI = (key: string) => {
|
||||||
|
return http.request<null>("delete", `/api/cache/cacheKey/${key}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**删除所有缓存 */
|
||||||
|
export const deleteAllCachedAPI = () => {
|
||||||
|
return http.request<null>("delete", `/api/cache/clearAll`);
|
||||||
|
};
|
||||||
|
|||||||
374
src/views/monitor/cache/list.vue
vendored
Normal file
374
src/views/monitor/cache/list.vue
vendored
Normal file
@@ -0,0 +1,374 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<el-row :gutter="10">
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-card style="height: calc(100vh - 155px)">
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="flex items-center justify-center">
|
||||||
|
<IconifyIconOffline :icon="Collection" />
|
||||||
|
<span class="header-title">缓存列表</span>
|
||||||
|
</div>
|
||||||
|
<el-button
|
||||||
|
link
|
||||||
|
type="primary"
|
||||||
|
size="large"
|
||||||
|
:icon="useRenderIcon(Refresh)"
|
||||||
|
@click="refreshCacheNames()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-table
|
||||||
|
v-loading="loading"
|
||||||
|
:data="cacheNames"
|
||||||
|
:height="tableHeight"
|
||||||
|
highlight-current-row
|
||||||
|
style="width: 100%"
|
||||||
|
@row-click="getCacheKeys"
|
||||||
|
>
|
||||||
|
<el-table-column label="序号" width="60" type="index" />
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
label="缓存名称"
|
||||||
|
align="center"
|
||||||
|
prop="cacheName"
|
||||||
|
:show-overflow-tooltip="true"
|
||||||
|
:formatter="nameFormatter"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
label="备注"
|
||||||
|
align="center"
|
||||||
|
prop="remark"
|
||||||
|
:show-overflow-tooltip="true"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
label="操作"
|
||||||
|
width="60"
|
||||||
|
align="center"
|
||||||
|
class-name="small-padding fixed-width"
|
||||||
|
>
|
||||||
|
<template #default="scope">
|
||||||
|
<el-popconfirm
|
||||||
|
confirm-button-text="确定"
|
||||||
|
cancel-button-text="取消"
|
||||||
|
icon="el-icon-info"
|
||||||
|
icon-color="red"
|
||||||
|
title="确定要删除此缓存名称吗?"
|
||||||
|
@confirm="handleClearCacheName(scope.row)"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<el-button
|
||||||
|
link
|
||||||
|
type="primary"
|
||||||
|
:icon="useRenderIcon(Delete)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-popconfirm>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-card style="height: calc(100vh - 155px)">
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="flex items-center justify-center">
|
||||||
|
<IconifyIconOffline :icon="Key" />
|
||||||
|
<span class="header-title">键名列表</span>
|
||||||
|
</div>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
link
|
||||||
|
size="large"
|
||||||
|
:icon="useRenderIcon(Refresh)"
|
||||||
|
@click="refreshCacheKeys()"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-table
|
||||||
|
v-loading="subLoading"
|
||||||
|
:data="cacheKeys"
|
||||||
|
:height="tableHeight"
|
||||||
|
highlight-current-row
|
||||||
|
style="width: 100%"
|
||||||
|
@row-click="handleCacheValue"
|
||||||
|
>
|
||||||
|
<el-table-column label="序号" width="60" type="index" />
|
||||||
|
<el-table-column
|
||||||
|
label="缓存键名"
|
||||||
|
align="center"
|
||||||
|
:show-overflow-tooltip="true"
|
||||||
|
:formatter="keyFormatter"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
label="操作"
|
||||||
|
width="60"
|
||||||
|
align="center"
|
||||||
|
class-name="small-padding fixed-width"
|
||||||
|
>
|
||||||
|
<template #default="scope">
|
||||||
|
<el-popconfirm
|
||||||
|
confirm-button-text="确定"
|
||||||
|
cancel-button-text="取消"
|
||||||
|
icon="el-icon-info"
|
||||||
|
icon-color="red"
|
||||||
|
title="确定要删除此缓存键名吗?"
|
||||||
|
@confirm="handleClearCacheKey(scope.row)"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<el-button
|
||||||
|
link
|
||||||
|
type="primary"
|
||||||
|
:icon="useRenderIcon(Delete)"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</el-popconfirm>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="8">
|
||||||
|
<el-card :bordered="false" style="height: calc(100vh - 155px)">
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="flex items-center justify-center">
|
||||||
|
<IconifyIconOffline :icon="Document" />
|
||||||
|
<span class="header-title">缓存内容</span>
|
||||||
|
</div>
|
||||||
|
<el-popconfirm
|
||||||
|
confirm-button-text="确定"
|
||||||
|
cancel-button-text="取消"
|
||||||
|
icon="el-icon-info"
|
||||||
|
icon-color="red"
|
||||||
|
title="确定要清理所有缓存吗?"
|
||||||
|
@confirm="handleClearCacheAll()"
|
||||||
|
>
|
||||||
|
<template #reference>
|
||||||
|
<el-button
|
||||||
|
style="float: right; padding: 3px 0"
|
||||||
|
link
|
||||||
|
type="primary"
|
||||||
|
:icon="useRenderIcon(Delete)"
|
||||||
|
>清理全部</el-button
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
</el-popconfirm>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<el-form :model="cacheForm">
|
||||||
|
<el-row :gutter="32">
|
||||||
|
<el-col :offset="1" :span="22">
|
||||||
|
<el-form-item label="缓存名称:" prop="cacheName">
|
||||||
|
<el-input v-model="cacheForm.cacheName" :readOnly="true" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :offset="1" :span="22">
|
||||||
|
<el-form-item label="缓存键名:" prop="cacheKey">
|
||||||
|
<el-input v-model="cacheForm.cacheKey" :readOnly="true" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :offset="1" :span="22">
|
||||||
|
<el-form-item label="缓存内容:" prop="cacheValue">
|
||||||
|
<el-input
|
||||||
|
v-model="cacheForm.cacheValue"
|
||||||
|
type="textarea"
|
||||||
|
:rows="8"
|
||||||
|
:readOnly="true"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, reactive } from "vue";
|
||||||
|
import {
|
||||||
|
getCachedKeysAPI,
|
||||||
|
getCachedNamesAPI,
|
||||||
|
getCachedInfoAPI,
|
||||||
|
deleteAllCachedAPI,
|
||||||
|
deleteCachedAPI,
|
||||||
|
deleteCachedKeyAPI
|
||||||
|
} from "@/api/monitor";
|
||||||
|
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||||
|
import Collection from "@iconify-icons/ep/collection";
|
||||||
|
import Key from "@iconify-icons/ep/key";
|
||||||
|
import Document from "@iconify-icons/ep/document";
|
||||||
|
import Delete from "@iconify-icons/ep/delete";
|
||||||
|
import Refresh from "@iconify-icons/ep/refresh";
|
||||||
|
import { message } from "@/utils/message";
|
||||||
|
defineOptions({
|
||||||
|
name: "CacheList"
|
||||||
|
});
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
const subLoading = ref(false);
|
||||||
|
const tableHeight = ref(window.innerHeight - 180);
|
||||||
|
const cacheNames = ref([]);
|
||||||
|
const cacheKeys = ref([]);
|
||||||
|
const cacheForm = reactive({
|
||||||
|
cacheName: "",
|
||||||
|
cacheKey: "",
|
||||||
|
cacheValue: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
const refreshCacheNames = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const res = await getCachedNamesAPI();
|
||||||
|
if (res.success) {
|
||||||
|
cacheNames.value = res.data;
|
||||||
|
}
|
||||||
|
message(res.msg, { type: res.success ? "success" : "error" });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取缓存名称列表失败", error);
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCacheKeys = async (row: any) => {
|
||||||
|
cacheForm.cacheName = row.cacheName;
|
||||||
|
cacheForm.cacheKey = "";
|
||||||
|
cacheForm.cacheValue = "";
|
||||||
|
subLoading.value = true;
|
||||||
|
try {
|
||||||
|
const res = await getCachedKeysAPI(row.cacheName);
|
||||||
|
if (res.success) {
|
||||||
|
cacheKeys.value = res.data;
|
||||||
|
}
|
||||||
|
message(res.msg, { type: res.success ? "success" : "error" });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取缓存键名列表失败", error);
|
||||||
|
} finally {
|
||||||
|
subLoading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const refreshCacheKeys = async () => {
|
||||||
|
if (cacheForm.cacheName) {
|
||||||
|
subLoading.value = true;
|
||||||
|
try {
|
||||||
|
const res = await getCachedKeysAPI(cacheForm.cacheName);
|
||||||
|
if (res.success) {
|
||||||
|
cacheKeys.value = res.data;
|
||||||
|
}
|
||||||
|
message(res.msg, { type: res.success ? "success" : "error" });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("刷新缓存键名列表失败", error);
|
||||||
|
} finally {
|
||||||
|
subLoading.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCacheValue = async (row: any) => {
|
||||||
|
cacheForm.cacheKey = row;
|
||||||
|
try {
|
||||||
|
const res = await getCachedInfoAPI(cacheForm.cacheName, row);
|
||||||
|
if (res.success) {
|
||||||
|
Object.assign(cacheForm, res.data);
|
||||||
|
}
|
||||||
|
message(res.msg, { type: res.success ? "success" : "error" });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取缓存内容失败", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClearCacheName = async (row: any) => {
|
||||||
|
try {
|
||||||
|
const res = await deleteCachedAPI(row.cacheName);
|
||||||
|
if (res.success) {
|
||||||
|
refreshCacheNames();
|
||||||
|
cacheKeys.value = [];
|
||||||
|
cacheForm.cacheName = "";
|
||||||
|
cacheForm.cacheKey = "";
|
||||||
|
cacheForm.cacheValue = "";
|
||||||
|
}
|
||||||
|
message(res.msg, { type: res.success ? "success" : "error" });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("清除缓存名称失败", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClearCacheKey = async (row: any) => {
|
||||||
|
try {
|
||||||
|
const res = await deleteCachedKeyAPI(row);
|
||||||
|
if (res.success) {
|
||||||
|
refreshCacheKeys();
|
||||||
|
cacheForm.cacheKey = "";
|
||||||
|
cacheForm.cacheValue = "";
|
||||||
|
}
|
||||||
|
message(res.msg, { type: res.success ? "success" : "error" });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("清除缓存键名失败", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClearCacheAll = async () => {
|
||||||
|
try {
|
||||||
|
const res = await deleteAllCachedAPI();
|
||||||
|
if (res.success) {
|
||||||
|
refreshCacheNames();
|
||||||
|
cacheKeys.value = [];
|
||||||
|
cacheForm.cacheName = "";
|
||||||
|
cacheForm.cacheKey = "";
|
||||||
|
cacheForm.cacheValue = "";
|
||||||
|
}
|
||||||
|
message(res.msg, { type: res.success ? "success" : "error" });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("清除所有缓存失败", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const nameFormatter = (row: any, column: any, cellValue: any) => {
|
||||||
|
return cellValue || "-";
|
||||||
|
};
|
||||||
|
|
||||||
|
const keyFormatter = (row: any, column: any, cellValue: any) => {
|
||||||
|
return row || "-";
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await refreshCacheNames();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.icon {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centered-descriptions {
|
||||||
|
:deep(.el-descriptions-item__container) {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-descriptions-item__label) {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.el-descriptions-item__content) {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user