Vue 实现Redis管理页面
一、效果图二、准备工作 1、所需接口 /redis-manage/del-key -> 删除指定的key,用于删除单个缓存 /redis-manage/del-keys -> 删除多个key,用于清空缓存 /redis-manage/info -> 获取Redis信息 /re...
·
一、效果图
二、准备工作
1、所需接口
/redis-manage/del-key -> 删除指定的key,用于删除单个缓存
/redis-manage/del-keys -> 删除多个key,用于清空缓存
/redis-manage/info -> 获取Redis信息
/redis-manage/key-value -> 获取key和value
/redis-manage/keys -> 获取key列表,使用正则来获取
/redis-manage/keys-count -> 统计key的个数
/redis-manage/value -> 根据指定的key获取value
2、所需文件
cache.js -> 用于请求后端
import axios from '@/libs/api.request'
import Qs from 'qs'
/**
* 获取Redis缓存信息
*/
export const redisCacheInfo = () => {
return axios.request({
url: '/redis-manage/info',
method: 'GET',
data: ''
})
}
/**
* 获取Redis指定的key,如不指定,则获取所有
*/
export const redisCacheKeys = (params) => {
return axios.request({
url: '/redis-manage/keys',
method: 'POST',
data: Qs.stringify(params)
})
}
/**
* 获取key的个数
*/
export const redisCacheKeysCount = () => {
return axios.request({
url: '/redis-manage/keys-count',
method: 'GET',
data: ''
})
}
/**
* 根据key获取value信息
*/
export const getValueByKey = (params) => {
return axios.request({
url: '/redis-manage/value',
method: 'POST',
data: Qs.stringify(params)
})
}
/**
* 根据key删除缓存信息
*/
export const delKey = (params) => {
return axios.request({
url: '/redis-manage/del-key',
method: 'POST',
data: Qs.stringify(params)
})
}
/**
* 删除所有缓存
*/
export const delKeys = (params) => {
return axios.request({
url: '/redis-manage/del-keys',
method: 'POST',
data: params
})
}
RedisCache.less -> 页面样式代码
.demo-split {
height: 700px;
border: 1px solid #dcdee2;
}
.demo-split-pane {
padding: 10px;
}
.demo-split-pane.no-padding {
height: 700px;
padding: 0;
}
.search-input {
width: 200px;
margin-right: 5px;
}
.search-btn {
margin-right: 5px;
}
.server-info-title {
text-align: center;
margin-bottom: 10px;
}
.server-info-basics {
text-align: center;
}
.server-key {
color: #2db7f5;
}
.server-clear-key {
color: #ed4014;
}
.server-value-divider {
margin: 10px;
}
.server-value-title {
padding-left: 20px;
}
.server-value-key {
color: #5eb95e;
}
.server-value-value {
background: rgba(94,185,94,.115);
height: 40px;
line-height: 40px;
text-align: center;
margin-left: 20px;
}
.server-value-val {
}
.server-key-key {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
RedisCache.vue -> 页面代码
<template>
<div>
<Card>
<p slot="title">
<Icon type="ios-ionitron"></Icon>Redis缓存管理
</p>
<a href="#" slot="extra" @click.prevent="searchKeys">
<Icon type="ios-refresh"></Icon>刷新
</a>
<div class="demo-split">
<Split v-model="splitDB">
<div slot="left" class="demo-split-pane no-padding">
<Split v-model="splitInfo" mode="vertical">
<div slot="top" class="demo-split-pane">
<Row style="margin-bottom: 10px;">
<i-col span="24">
<Input v-model="searchPattern" placeholder="请输入key搜索..." class="search-input" @on-enter="searchKeys" />
<InputNumber v-model="searchCount" placeholder="请输入搜索的个数" style="width: 80px; margin-right: 5px;" @on-enter="searchKeys" />
<Button type="primary" icon="ios-search" @click="searchKeys" class="search-btn">搜索</Button>
<Tooltip content="清空缓存,谨慎操作" placement="bottom">
<Button type="error" icon="md-close" @click="deleteKeys">清空keys</Button>
</Tooltip>
</i-col>
</Row>
<Collapse simple @on-change="switchCollapse">
<Panel name="db">数据库-0({{keysCount}})
<p slot="content">
<Spin fix v-if="keysSpin"></Spin>
<Scroll height="160">
<Row>
<div v-for="item in keysList" :key="item.key">
<i-col span="10" class="server-key-key" style="margin-bottom: 5px;">
<a href="javascript:;" @click="getValueByKey(item.key)" class="server-key">{{item.key}}</a>
</i-col>
<i-col span="2">
<Tooltip content="删除缓存,谨慎操作" placement="left">
<a href="javascript:;" @click="deleteKey(item.key)" class="server-clear-key"><Icon type="md-close" /></a>
</Tooltip>
</i-col>
</div>
</Row>
</Scroll>
</p>
</Panel>
</Collapse>
</div>
<div slot="bottom" class="demo-split-pane">
<Divider class="server-value-divider"></Divider>
<Row class="server-value-title">
<i-col span="2">
<strong class="server-value-key">Key:</strong>
</i-col>
<i-col span="22">{{valueInfo.key}}</i-col>
</Row>
<Divider class="server-value-divider"></Divider>
<Row class="server-value-title">
<i-col span="2">
<strong class="server-value-key">Size:</strong>
</i-col>
<i-col span="22">{{valueInfo.size}}</i-col>
</Row>
<Divider class="server-value-divider"></Divider>
<Row class="server-value-title">
<i-col span="2">
<strong class="server-value-key">TTL:</strong>
</i-col>
<i-col span="22">{{valueInfo.expire}}{{valueInfo.expireFormat}}</i-col>
</Row>
<Divider class="server-value-divider" style="margin-bottom: 0px;"></Divider>
<Row class="server-value-value">
<i-col span="22">
<strong class="server-value-key">Value</strong>
</i-col>
<i-col span="2">
<Tooltip content="删除缓存,谨慎操作">
<Button type="text" icon="md-close" class="server-clear-key"/>
</Tooltip>
</i-col>
</Row>
<Divider class="server-value-divider" style="margin-top: 0px;"></Divider>
<Row class="server-value-val">
<Scroll height="200">
<pre>
{{valueInfo.value}}
</pre>
</Scroll>
</Row>
</div>
</Split>
</div>
<div slot="right" class="demo-split-pane">
<h3 class="server-info-title">Redis 服务器信息</h3>
<Divider>基本信息</Divider>
<Row class="server-info-title">
<i-col span="12">
<CellGroup>
<Cell title="Redis 版本" :label="redisInfo.gcc_version"/>
<Cell title="已执行的命令" :label="redisInfo.total_commands_processed"/>
</CellGroup>
</i-col>
<i-col span="12">
<CellGroup>
<Cell title="已使用的内存" :label="redisInfo.used_memory_rss"/>
<Cell title="正常运行时间" :label="redisInfo.uptime_in_days"/>
</CellGroup>
</i-col>
</Row>
<Divider>详细信息</Divider>
<CellGroup>
<Scroll height="290">
<Cell title="arch_bits" :extra="redisInfo.arch_bits"/>
<Cell title="config_file" :extra="redisInfo.config_file"/>
<Cell title="hz" :extra="redisInfo.hz"/>
<Cell title="lru_clock" :extra="redisInfo.lru_clock"/>
<Cell title="multiplexing_api" :extra="redisInfo.multiplexing_api"/>
<Cell title="os" :extra="redisInfo.os"/>
<Cell title="process_id" :extra="redisInfo.process_id"/>
<Cell title="redis_build_id" :extra="redisInfo.redis_build_id"/>
<Cell title="redis_git_drity" :extra="redisInfo.redis_git_dirty"/>
<Cell title="redis_git_sha1" :extra="redisInfo.redis_git_sha1"/>
<Cell title="redis_mode" :extra="redisInfo.redis_mode"/>
<Cell title="redis_version" :extra="redisInfo.redis_version"/>
<Cell title="run_id" :extra="redisInfo.run_id"/>
<Cell title="tcp_port" :extra="redisInfo.tcp_port"/>
<Cell title="uptime_in_days" :extra="redisInfo.uptime_in_days"/>
<Cell title="uptime_in_seconds" :extra="redisInfo.uptime_in_seconds"/>
</Scroll>
</CellGroup>
</div>
</Split>
</div>
</Card>
</div>
</template>
<script>
import './RedisCache.less'
var JWT_TOKEN = "jwt_token::"
import {
redisCacheInfo,
redisCacheKeys,
redisCacheKeysCount,
getValueByKey,
delKey,
delKeys
} from '@/api/cache'
export default {
name: 'RedisCache',
components: {},
data() {
return {
splitDB: 0.6,
splitInfo: 0.2,
searchPattern: '*',
searchCount: 1,
redisInfo: {
aof_rewrite_scheduled: 'N/A',
number_of_cached_scripts: 'N/A',
mem_clients_slaves: 'N/A',
keyspace_misses: 'N/A',
mem_allocator: 'N/A',
multiplexing_api: 'N/A',
aof_last_write_status: 'N/A',
used_memory_peak_perc: 'N/A',
run_id: 'N/A',
uptime_in_seconds: 'N/A',
maxmemory: 'N/A',
active_defrag_hits: 'N/A',
atomicvar_api: 'N/A',
total_system_memory_human: 'N/A',
gcc_version: 'N/A',
second_repl_offset: 'N/A',
arch_bits: 'N/A',
master_repl_offset: 'N/A',
instantaneous_output_kbps: 'N/A',
total_commands_processed: 'N/A',
repl_backlog_size: 'N/A',
sync_full: 'N/A',
sync_partial_err: 'N/A',
aof_last_cow_size: 'N/A',
configured_hz: 'N/A',
used_memory_startup: 'N/A',
mem_clients_normal: 'N/A',
used_cpu_user: 'N/A',
aof_enabled: 'N/A',
redis_mode: 'N/A',
rdb_changes_since_last_save: 'N/A',
used_memory_lua: 'N/A',
redis_build_id: 'N/A',
connected_slaves: 'N/A',
expired_keys: 'N/A',
used_memory: 'N/A',
active_defrag_misses: 'N/A',
active_defrag_key_misses: 'N/A',
used_memory_rss: 'N/A',
rdb_last_bgsave_status: 'N/A',
process_id: 'N/A',
rejected_connections: 'N/A',
master_replid: 'N/A',
used_memory_rss_human: 'N/A',
used_memory_scripts: 'N/A',
rdb_bgsave_in_progress: 'N/A',
rdb_last_cow_size: 'N/A',
cluster_enabled: 'N/A',
tcp_port: 'N/A',
os: 'N/A',
mem_replication_backlog: 'N/A',
aof_current_rewrite_time_sec: 'N/A',
allocator_rss_ratio: 'N/A',
used_memory_overhead: 'N/A',
repl_backlog_histlen: 'N/A',
slave_expires_tracked_keys: 'N/A',
used_cpu_sys: 'N/A',
role: 'N/A',
used_memory_dataset_perc: 'N/A',
expired_stale_perc: 'N/A',
allocator_frag_ratio: 'N/A',
client_recent_max_input_buffer: 'N/A',
aof_last_bgrewrite_status: 'N/A',
used_memory_peak_human: 'N/A',
hz: 'N/A',
used_memory_human: 'N/A',
maxmemory_policy: 'N/A',
rss_overhead_ratio: 'N/A',
mem_fragmentation_ratio: 'N/A',
rdb_last_bgsave_time_sec: 'N/A',
allocator_allocated: 'N/A',
used_memory_dataset: 'N/A',
blocked_clients: 'N/A',
used_cpu_sys_children: 'N/A',
repl_backlog_active: 'N/A',
used_cpu_user_children: 'N/A',
sync_partial_ok: 'N/A',
aof_rewrite_in_progress: 'N/A',
redis_git_sha1: 'N/A',
rdb_current_bgsave_time_sec: 'N/A',
active_defrag_running: 'N/A',
aof_last_rewrite_time_sec: 'N/A',
master_replid2: 'N/A',
config_file: 'N/A',
lazyfree_pending_objects: 'N/A',
used_memory_scripts_human: 'N/A',
loading: 'N/A',
allocator_rss_bytes: 'N/A',
db3: 'N/A',
pubsub_channels: 'N/A',
db1: 'N/A',
used_memory_lua_human: 'N/A',
db0: 'N/A',
active_defrag_key_hits: 'N/A',
allocator_frag_bytes: 'N/A',
migrate_cached_sockets: 'N/A',
redis_git_dirty: 'N/A',
total_system_memory: 'N/A',
mem_aof_buffer: 'N/A',
rss_overhead_bytes: 'N/A',
client_recent_max_output_buffer: 'N/A',
connected_clients: 'N/A',
mem_fragmentation_bytes: 'N/A',
lru_clock: 'N/A',
pubsub_patterns: 'N/A',
expired_time_cap_reached_count: 'N/A',
repl_backlog_first_byte_offset: 'N/A',
total_net_output_bytes: 'N/A',
executable: 'N/A',
evicted_keys: 'N/A',
total_connections_received: 'N/A',
allocator_active: 'N/A',
mem_not_counted_for_evict: 'N/A',
redis_version: 'N/A',
total_net_input_bytes: 'N/A',
latest_fork_usec: 'N/A',
maxmemory_human: 'N/A',
used_memory_peak: 'N/A',
allocator_resident: 'N/A',
keyspace_hits: 'N/A',
uptime_in_days: 'N/A',
instantaneous_input_kbps: 'N/A',
instantaneous_ops_per_sec: 'N/A',
rdb_last_save_time: 'N/A'
},
keysList: '',
keysCount: 0,
keysSpin: false,
valueInfo: {
key: '',
value: '',
size: '',
expire: '',
expireFormat: ''
}
}
},
computed: {},
mounted() {
this.getRedisCacheInfo()
this.getKeysCount()
// this.searchKeys()
},
methods: {
// 切换数据库面板
switchCollapse(keys) {
if (keys.length === 0) {
// 关闭面板
this.splitInfo = 0.2
this.keysList = ''
} else {
// 开启面板
this.splitInfo = 0.4
this.searchKeys()
}
},
// 获取Redis缓存信息
getRedisCacheInfo() {
redisCacheInfo()
.then(res => {
const data = res.data
if (data.code === 1001) {
this.redisInfo = data.data
this.redisInfo.uptime_in_days = this.redisInfo.uptime_in_days + "天"
this.redisInfo.uptime_in_seconds = this.formaturDing(this.redisInfo.uptime_in_seconds)
this.redisInfo.used_memory_rss = (this.redisInfo.used_memory_rss / 1024 / 1024).toFixed(2) + "M"
} else {
this.$Message.error(data.message)
}
})
.catch(err => {
this.$Message.error(err)
})
},
// 获取key的个数
getKeysCount() {
redisCacheKeysCount()
.then(res => {
const data = res.data
if (data.code === 1001) {
this.keysCount = data.data
} else {
this.$Message.error(data.message)
}
})
.catch(err => {
this.$Message.error(err)
})
},
// 查询key
searchKeys() {
if (this.searchCount === null) {
this.searchCount = 1
}
var params = {
count: this.searchCount,
pattern : this.searchPattern
}
this.keysSpin = true
redisCacheKeys(params)
.then(res => {
this.keysSpin = false
const data = res.data
if (data.code === 1001) {
this.getKeysCount()
if (data.data.total === 0) {
this.$Message.error('未获取到key')
return
}
this.valueInfo = ''
this.keysList = data.data.rows
} else {
this.$Message.error(data.message)
}
})
.catch(err => {
this.$Message.error(err)
})
},
// 根据key查询value的值信息
getValueByKey(key) {
if (key === '') {
this.$Message.error('key为空')
return
}
var params = {
key: key
}
getValueByKey(params)
.then(res => {
const data = res.data
if (data.code === 1001) {
this.valueInfo = data.data
if (this.valueInfo.expire !== -1) {
const time = (this.valueInfo.expire / 1000).toFixed(0)
this.valueInfo.expire = time + " s"
this.valueInfo.expireFormat = "(" + this.formaturDing(time) + ")"
}
this.valueInfo.size = this.valueInfo.size + " byte"
} else {
this.$Message.error(data.message)
}
})
.catch(err => {
this.$Message.error(err)
})
},
// 删除key
deleteKey(key) {
if (key === '') {
this.$Message.error('key为空')
return
}
if (key.indexOf(JWT_TOKEN) != -1) {
this.$Message.error("该缓存不可删除")
return
}
var params = {
key: key
}
delKey(params)
.then(res => {
const data = res.data
if (data.code === 1001) {
this.$Message.info(data.message)
this.searchKeys()
} else {
this.$Message.error(data.message)
}
})
.catch(err => {
this.$Message.error(err)
})
},
// 清空缓存
deleteKeys() {
if (this.keysCount <= 0 || this.keysList.length <= 0) {
this.$Message.error("未获取到缓存,不需要清空")
return
}
var keys = [];
this.keysList.forEach(key => {
if (key.key.indexOf(JWT_TOKEN) == -1) {
keys.push(key.key)
}
})
var params = {
keys: keys
}
console.log(keys)
delKeys(keys)
.then(res => {
const data = res.data
if (data.code === 1001) {
this.$Message.info(data.message)
this.searchKeys()
} else {
this.$Message.error(data.message)
}
})
.catch(err => {
this.$Message.error(err)
})
},
// 格式化时间
formaturDing(mss) {
var days = parseInt(mss / (60 * 60 * 24))
var hours = parseInt((mss % (60 * 60 * 24)) / (60 * 60))
var minutes = parseInt((mss % (60 * 60)) / 60)
var seconds = mss % 60
return days + ' 天 ' + hours + ' 小时 ' + minutes + ' 分 ' + seconds + ' 秒 '
}
}
}
</script>
这里代码都挺简单的,没啥逻辑,这里就不做多的解释了,主要是样式和页面布局。
更多推荐
已为社区贡献11条内容
所有评论(0)