Browse Source

feat(vben5): Add the cache management module package

pull/1470/head
colin 3 weeks ago
parent
commit
3ef0010716
  1. 1
      apps/vben5/apps/app-antd/package.json
  2. 15
      apps/vben5/apps/app-antd/src/views/caching/caches/index.vue
  3. 37
      apps/vben5/packages/@abp/cache-management/package.json
  4. 1
      apps/vben5/packages/@abp/cache-management/src/api/index.ts
  5. 93
      apps/vben5/packages/@abp/cache-management/src/api/useCacheManagementApi.ts
  6. 147
      apps/vben5/packages/@abp/cache-management/src/components/CacheEditModal.vue
  7. 291
      apps/vben5/packages/@abp/cache-management/src/components/CacheKeyTable.vue
  8. 121
      apps/vben5/packages/@abp/cache-management/src/components/CacheRefreshModal.vue
  9. 1
      apps/vben5/packages/@abp/cache-management/src/components/index.ts
  10. 8
      apps/vben5/packages/@abp/cache-management/src/constants/permissions.ts
  11. 3
      apps/vben5/packages/@abp/cache-management/src/index.ts
  12. 48
      apps/vben5/packages/@abp/cache-management/src/types/index.ts
  13. 6
      apps/vben5/packages/@abp/cache-management/tsconfig.json

1
apps/vben5/apps/app-antd/package.json

@ -29,6 +29,7 @@
"@abp/account": "workspace:*",
"@abp/ai-management": "workspace:*",
"@abp/auditing": "workspace:*",
"@abp/cache-management": "workspace:*",
"@abp/components": "workspace:*",
"@abp/core": "workspace:*",
"@abp/data-protection": "workspace:*",

15
apps/vben5/apps/app-antd/src/views/caching/caches/index.vue

@ -0,0 +1,15 @@
<script lang="ts" setup>
import { Page } from '@vben/common-ui';
import { CacheKeyTable } from '@abp/cache-management';
defineOptions({
name: 'Vben5CacheKeys',
});
</script>
<template>
<Page>
<CacheKeyTable />
</Page>
</template>

37
apps/vben5/packages/@abp/cache-management/package.json

@ -0,0 +1,37 @@
{
"name": "@abp/cache-management",
"version": "10.0.2",
"homepage": "https://github.com/colinin/abp-next-admin",
"bugs": "https://github.com/colinin/abp-next-admin/issues",
"repository": {
"type": "git",
"url": "git+https://github.com/colinin/abp-next-admin.git",
"directory": "packages/@abp/cache-management"
},
"license": "MIT",
"type": "module",
"sideEffects": [
"**/*.css"
],
"exports": {
".": {
"types": "./src/index.ts",
"default": "./src/index.ts"
}
},
"dependencies": {
"@abp/core": "workspace:*",
"@abp/request": "workspace:*",
"@abp/ui": "workspace:*",
"@ant-design/icons-vue": "catalog:",
"@vben/access": "workspace:*",
"@vben/common-ui": "workspace:*",
"@vben/hooks": "workspace:*",
"@vben/icons": "workspace:*",
"@vben/locales": "workspace:*",
"ant-design-vue": "catalog:",
"dayjs": "catalog:",
"vue": "catalog:",
"vxe-table": "catalog:"
}
}

1
apps/vben5/packages/@abp/cache-management/src/api/index.ts

@ -0,0 +1 @@
export { useCacheManagementApi } from './useCacheManagementApi';

93
apps/vben5/packages/@abp/cache-management/src/api/useCacheManagementApi.ts

@ -0,0 +1,93 @@
import type {
CacheKeyInput,
CacheKeysDto,
CacheRefreshInput,
CacheRemoveKeysInput,
CacheSetInput,
CacheValueDto,
GetCacheKeysInput,
} from '../types';
import { useRequest } from '@abp/request';
/** 缓存管理API接口 */
export function useCacheManagementApi() {
const apiPrefix = '/api/caching-management/cache';
const { cancel, request } = useRequest();
/**
*
* @param input
*/
function getKeysApi(input?: GetCacheKeysInput): Promise<CacheKeysDto> {
return request<CacheKeysDto>(`${apiPrefix}/keys`, {
method: 'GET',
params: input,
});
}
/**
*
* @param input
*/
function getKeyValueApi(input: CacheKeyInput): Promise<CacheValueDto> {
return request<CacheValueDto>(`${apiPrefix}/value`, {
method: 'GET',
params: input,
});
}
/**
*
* @param input
*/
function setValueApi(input: CacheSetInput): Promise<void> {
return request(`${apiPrefix}/set`, {
method: 'PUT',
data: input,
});
}
/**
*
* @param input
*/
function refreshApi(input: CacheRefreshInput): Promise<void> {
return request(`${apiPrefix}/refresh`, {
method: 'PUT',
data: input,
});
}
/**
*
* @param input
*/
function removeApi(input: CacheKeyInput): Promise<void> {
return request(`${apiPrefix}/remove`, {
method: 'DELETE',
params: input,
});
}
/**
*
* @param input
*/
function bulkRemoveApi(input: CacheRemoveKeysInput): Promise<void> {
return request(`${apiPrefix}/bulk/remove`, {
method: 'DELETE',
data: input,
});
}
return {
cancel,
getKeysApi,
getKeyValueApi,
refreshApi,
setValueApi,
removeApi,
bulkRemoveApi,
};
}

147
apps/vben5/packages/@abp/cache-management/src/components/CacheEditModal.vue

@ -0,0 +1,147 @@
<script setup lang="ts">
import { defineEmits, defineOptions } from 'vue';
import { useVbenForm, useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { toDate } from '@abp/core';
import { useMessage } from '@abp/ui';
import { Alert } from 'ant-design-vue';
import { useCacheManagementApi } from '../api/useCacheManagementApi';
defineOptions({
name: 'CacheEditModal',
});
const emit = defineEmits<{
(event: 'change', key: string): void;
}>();
const message = useMessage();
const { getKeyValueApi, setValueApi } = useCacheManagementApi();
const [Form, formApi] = useVbenForm({
commonConfig: {
componentProps: {
class: 'w-full',
},
},
handleSubmit: onSubmit,
schema: [
{
component: 'Textarea',
disabled: true,
fieldName: 'key',
label: $t('CachingManagement.DisplayName:Key'),
rules: 'required',
componentProps: {
autoSize: {
minRows: 3,
},
},
},
{
component: 'DatePicker',
disabled: true,
fieldName: 'absoluteExpiration',
label: $t('CachingManagement.DisplayName:AbsoluteExpiration'),
componentProps: {
format: 'YYYY-MM-DD HH:mm:ss',
},
},
{
component: 'Input',
disabled: true,
fieldName: 'type',
label: $t('CachingManagement.DisplayName:Type'),
},
{
component: 'InputNumber',
disabled: true,
fieldName: 'size',
label: $t('CachingManagement.DisplayName:Size'),
},
{
component: 'Textarea',
fieldName: 'value',
label: $t('CachingManagement.DisplayName:Values'),
rules: 'required',
componentProps: {
autoSize: {
minRows: 3,
maxRows: 8,
},
showCount: true,
},
},
],
showDefaultActions: false,
});
const [Modal, modalApi] = useVbenModal({
class: 'w-1/3',
draggable: true,
fullscreenButton: false,
onCancel() {
modalApi.close();
},
onConfirm: async () => {
await formApi.validateAndSubmitForm();
},
onOpenChange: async (isOpen: boolean) => {
if (isOpen) {
try {
modalApi.setState({ loading: true });
const { key } = modalApi.getData();
await onGet(key);
} finally {
modalApi.setState({ loading: false });
}
}
},
title: $t('CachingManagement.CacheInfo'),
});
async function onGet(key: string) {
const cacheValue = await getKeyValueApi({ key });
formApi.setValues({
key,
absoluteExpiration: toDate(cacheValue.expiration),
type: cacheValue.type,
size: cacheValue.size,
value: cacheValue.values.data,
});
}
async function onSubmit(input: Record<string, any>) {
modalApi.lock();
try {
await setValueApi({
key: input.key,
value: input.value,
absoluteExpiration: input.absoluteExpiration,
});
message.success($t('AbpUi.SavedSuccessfully'));
emit('change', input.key);
modalApi.close();
} finally {
modalApi.unlock();
}
}
</script>
<template>
<Modal>
<div class="flex flex-col gap-4">
<Alert
closable
show-icon
type="warning"
:message="$t('CachingManagement.EditCacheValueAlertMessage')"
/>
<Form />
</div>
</Modal>
</template>
<style scoped></style>

291
apps/vben5/packages/@abp/cache-management/src/components/CacheKeyTable.vue

@ -0,0 +1,291 @@
<script setup lang="ts">
import type { VxeGridListeners, VxeGridProps } from '@abp/ui';
import type { VbenFormProps } from '@vben/common-ui';
import { computed, defineAsyncComponent, h, onMounted, ref } from 'vue';
import { useAccess } from '@vben/access';
import { confirm, useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { sortby } from '@abp/core';
import { useMessage, useVbenVxeGrid } from '@abp/ui';
import {
DeleteOutlined,
EditOutlined,
ReloadOutlined,
} from '@ant-design/icons-vue';
import { Button } from 'ant-design-vue';
import { useCacheManagementApi } from '../api/useCacheManagementApi';
import { CachingManagementPermissions } from '../constants/permissions';
defineOptions({
name: 'CacheKeyTable',
});
interface CacheVto {
key: string;
}
const cacheKeys = ref<CacheVto[]>([]);
const selectKeys = ref<string[]>([]);
const message = useMessage();
const { hasAccessByCodes } = useAccess();
const { bulkRemoveApi, getKeysApi, removeApi } = useCacheManagementApi();
const isBulkDeleteEnabled = computed(() => {
if (selectKeys.value.length === 0) {
return false;
}
return hasAccessByCodes([CachingManagementPermissions.Delete]);
});
const formOptions: VbenFormProps = {
collapsed: false,
handleReset: onReset,
async handleSubmit(params) {
await onGet(params);
},
schema: [
{
component: 'Input',
fieldName: 'prefix',
label: $t('CachingManagement.DisplayName:Prefix'),
},
{
component: 'Input',
fieldName: 'filter',
label: $t('AbpUi.Search'),
},
],
showCollapseButton: true,
submitOnEnter: true,
};
const gridOptions: VxeGridProps<CacheVto> = {
columns: [
{
align: 'center',
type: 'checkbox',
width: 50,
},
{
align: 'center',
type: 'seq',
width: 50,
},
{
align: 'left',
field: 'key',
minWidth: 150,
sortable: true,
title: $t('CachingManagement.DisplayName:Key'),
},
{
field: 'action',
fixed: 'right',
visible: hasAccessByCodes([
CachingManagementPermissions.Default,
CachingManagementPermissions.Refresh,
CachingManagementPermissions.ManageValue,
]),
slots: { default: 'action' },
title: $t('AbpUi.Actions'),
width: 260,
},
],
expandConfig: {
accordion: true,
padding: true,
trigger: 'row',
height: 300,
},
exportConfig: {},
keepSource: true,
proxyConfig: {
ajax: {
query: async ({ page, sort }) => {
let items = sortby(cacheKeys.value, sort.field);
if (sort.order === 'desc') {
items = items.toReversed();
}
const result = {
totalCount: cacheKeys.value.length,
items: items.slice(
(page.currentPage - 1) * page.pageSize,
page.currentPage * page.pageSize,
),
};
return new Promise((resolve) => {
resolve(result);
});
},
},
response: {
total: 'totalCount',
list: 'items',
},
},
toolbarConfig: {
custom: true,
export: true,
refresh: false,
zoom: true,
},
};
const gridEvents: VxeGridListeners<CacheVto> = {
checkboxAll: (params) => {
selectKeys.value = params.records.map((x) => x.key);
},
checkboxChange: (params) => {
selectKeys.value = params.records.map((x) => x.key);
},
sortChange: () => {
gridApi.query();
},
};
const [Grid, gridApi] = useVbenVxeGrid({
formOptions,
gridEvents,
gridOptions,
});
const [CacheRefreshModal, refreshModalApi] = useVbenModal({
connectedComponent: defineAsyncComponent(
() => import('./CacheRefreshModal.vue'),
),
});
const [CacheEditModal, editModalApi] = useVbenModal({
connectedComponent: defineAsyncComponent(
() => import('./CacheEditModal.vue'),
),
});
async function onGet(input?: Record<string, string>) {
try {
gridApi.setLoading(true);
const result = await getKeysApi(input);
cacheKeys.value = result.keys.map((key) => {
return {
key,
};
});
setTimeout(() => gridApi.reload(), 100);
} finally {
gridApi.setLoading(false);
}
}
async function onReset() {
await gridApi.formApi.resetForm();
const input = await gridApi.formApi.getValues();
await onGet(input);
}
function onUpdate(row: CacheVto) {
editModalApi.setData(row);
editModalApi.open();
}
function onRefresh(row: CacheVto) {
refreshModalApi.setData(row);
refreshModalApi.open();
}
function onBulkDelete() {
confirm({
centered: true,
content: $t('CachingManagement.MultipleCacheWillBeDeletedMessage'),
beforeClose: async ({ isConfirm }) => {
if (isConfirm) {
try {
await bulkRemoveApi({ keys: selectKeys.value });
message.success($t('AbpUi.DeletedSuccessfully'));
onGet();
return true;
} catch {
return false;
}
}
},
icon: 'warning',
title: $t('AbpUi.AreYouSure'),
});
}
function onDelete(row: CacheVto) {
confirm({
centered: true,
content: $t('CachingManagement.MultipleCacheWillBeDeletedMessage'),
beforeClose: async ({ isConfirm }) => {
if (isConfirm) {
try {
await removeApi({ key: row.key });
message.success($t('AbpUi.DeletedSuccessfully'));
onGet();
return true;
} catch {
return false;
}
}
},
icon: 'warning',
title: $t('AbpUi.AreYouSure'),
});
}
onMounted(onGet);
</script>
<template>
<Grid :table-title="$t('CachingManagement.Caches')">
<template #toolbar-tools>
<Button
v-if="isBulkDeleteEnabled"
:icon="h(DeleteOutlined)"
type="primary"
danger
ghost
@click="onBulkDelete"
>
{{ $t('AbpUi.Delete') }}
</Button>
</template>
<template #action="{ row }">
<Button
:icon="h(EditOutlined)"
type="link"
v-access:code="[CachingManagementPermissions.ManageValue]"
@click="onUpdate(row)"
>
{{ $t('AbpUi.Edit') }}
</Button>
<Button
:icon="h(DeleteOutlined)"
danger
type="link"
v-access:code="[CachingManagementPermissions.Delete]"
@click="onDelete(row)"
>
{{ $t('AbpUi.Delete') }}
</Button>
<Button
:icon="h(ReloadOutlined)"
type="link"
v-access:code="[CachingManagementPermissions.Refresh]"
@click="onRefresh(row)"
>
{{ $t('AbpUi.Refresh') }}
</Button>
</template>
</Grid>
<CacheEditModal @change="() => onGet()" />
<CacheRefreshModal @change="() => onGet()" />
</template>
<style scoped></style>

121
apps/vben5/packages/@abp/cache-management/src/components/CacheRefreshModal.vue

@ -0,0 +1,121 @@
<script setup lang="ts">
import { defineEmits, defineOptions } from 'vue';
import { useVbenForm, useVbenModal } from '@vben/common-ui';
import { $t } from '@vben/locales';
import { toDate } from '@abp/core';
import { useMessage } from '@abp/ui';
import { Alert } from 'ant-design-vue';
import { useCacheManagementApi } from '../api/useCacheManagementApi';
defineOptions({
name: 'CacheRefreshModal',
});
const emit = defineEmits<{
(event: 'change', key: string): void;
}>();
const message = useMessage();
const { getKeyValueApi, refreshApi } = useCacheManagementApi();
const [Form, formApi] = useVbenForm({
commonConfig: {
//
componentProps: {
class: 'w-full',
},
},
handleSubmit: onSubmit,
schema: [
{
component: 'Textarea',
disabled: true,
fieldName: 'key',
label: $t('CachingManagement.DisplayName:Key'),
rules: 'required',
componentProps: {
autoSize: {
minRows: 3,
maxRows: 8,
},
showCount: true,
},
},
{
component: 'DatePicker',
fieldName: 'absoluteExpiration',
label: $t('CachingManagement.DisplayName:AbsoluteExpiration'),
rules: 'required',
componentProps: {
format: 'YYYY-MM-DD HH:mm:ss',
},
},
],
showDefaultActions: false,
});
const [Modal, modalApi] = useVbenModal({
class: 'w-1/3',
draggable: true,
fullscreenButton: false,
onCancel() {
modalApi.close();
},
onConfirm: async () => {
await formApi.validateAndSubmitForm();
},
onOpenChange: async (isOpen: boolean) => {
if (isOpen) {
try {
modalApi.setState({ loading: true });
const { key } = modalApi.getData();
await onGet(key);
} finally {
modalApi.setState({ loading: false });
}
}
},
title: $t('CachingManagement.CacheInfo'),
});
async function onGet(key: string) {
const cacheValue = await getKeyValueApi({ key });
formApi.setValues({
key,
absoluteExpiration: toDate(cacheValue.expiration),
});
}
async function onSubmit(input: Record<string, any>) {
modalApi.lock();
try {
await refreshApi({
key: input.key,
absoluteExpiration: input.absoluteExpiration,
});
message.success($t('AbpUi.SavedSuccessfully'));
emit('change', input.key);
modalApi.close();
} finally {
modalApi.unlock();
}
}
</script>
<template>
<Modal>
<div class="flex flex-col gap-4">
<Alert
closable
show-icon
type="warning"
:message="$t('CachingManagement.EditCacheValueAlertMessage')"
/>
<Form />
</div>
</Modal>
</template>
<style scoped></style>

1
apps/vben5/packages/@abp/cache-management/src/components/index.ts

@ -0,0 +1 @@
export { default as CacheKeyTable } from './CacheKeyTable.vue';

8
apps/vben5/packages/@abp/cache-management/src/constants/permissions.ts

@ -0,0 +1,8 @@
const CachePrefix = 'AbpCachingManagement.Cache';
export const CachingManagementPermissions = {
Refresh: `${CachePrefix}.Refresh`,
Default: CachePrefix,
Delete: `${CachePrefix}.Delete`,
ManageValue: `${CachePrefix}.ManageValue`,
};

3
apps/vben5/packages/@abp/cache-management/src/index.ts

@ -0,0 +1,3 @@
export * from './api';
export * from './components';
export * from './types';

48
apps/vben5/packages/@abp/cache-management/src/types/index.ts

@ -0,0 +1,48 @@
interface GetCacheKeysInput {
filter?: string;
marker?: string;
prefix?: string;
}
interface CacheKeyInput {
key: string;
}
interface CacheSetInput {
absoluteExpiration?: Date;
key: string;
slidingExpiration?: Date;
value?: string;
}
interface CacheRefreshInput {
absoluteExpiration?: Date;
key: string;
slidingExpiration?: Date;
}
interface CacheKeysDto {
keys: string[];
nextMarker: string;
}
interface CacheValueDto {
expiration?: Date;
size: number;
type: string;
values: Record<string, any>;
}
interface CacheRemoveKeysInput {
keys: string[];
}
export type {
CacheKeyInput,
CacheKeysDto,
CacheRefreshInput,
CacheRemoveKeysInput,
CacheSetInput,
CacheValueDto,
GetCacheKeysInput,
};

6
apps/vben5/packages/@abp/cache-management/tsconfig.json

@ -0,0 +1,6 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "@vben/tsconfig/web.json",
"include": ["src"],
"exclude": ["node_modules"]
}
Loading…
Cancel
Save