@befly-addon/admin 1.8.6 → 1.8.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adminViews/config/dict/components/edit.vue +16 -8
- package/adminViews/config/dict/index.vue +3 -3
- package/adminViews/config/dictType/components/edit.vue +16 -8
- package/adminViews/config/dictType/index.vue +2 -1
- package/adminViews/config/system/components/edit.vue +17 -9
- package/adminViews/config/system/index.vue +2 -1
- package/adminViews/index/components/addonList.vue +10 -2
- package/adminViews/index/components/environmentInfo.vue +12 -2
- package/adminViews/index/components/operationLogs.vue +16 -2
- package/adminViews/index/components/performanceMetrics.vue +9 -3
- package/adminViews/index/components/serviceStatus.vue +11 -4
- package/adminViews/index/components/systemNotifications.vue +13 -2
- package/adminViews/index/components/systemOverview.vue +3 -2
- package/adminViews/index/components/systemResources.vue +10 -3
- package/adminViews/index/components/userInfo.vue +19 -5
- package/adminViews/log/email/index.vue +21 -12
- package/adminViews/log/login/index.vue +2 -1
- package/adminViews/log/operate/index.vue +2 -1
- package/adminViews/login_1/index.vue +11 -8
- package/adminViews/people/admin/components/edit.vue +17 -9
- package/adminViews/people/admin/index.vue +2 -1
- package/adminViews/permission/api/index.vue +3 -2
- package/adminViews/permission/menu/index.vue +3 -2
- package/adminViews/permission/role/components/api.vue +5 -5
- package/adminViews/permission/role/components/edit.vue +16 -8
- package/adminViews/permission/role/components/menu.vue +5 -5
- package/adminViews/permission/role/index.vue +2 -1
- package/apis/admin/cacheRefresh.ts +15 -3
- package/apis/api/all.ts +7 -14
- package/apis/menu/all.ts +21 -34
- package/apis/role/apis.ts +4 -12
- package/apis/role/menuSave.ts +10 -2
- package/apis/role/menus.ts +4 -11
- package/package.json +3 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<PageDialog v-model="visible" :title="actionType === 'add' ? '添加字典项' : '编辑字典项'" @confirm="handleSubmit">
|
|
3
|
-
<TForm :data="$Data.formData" :rules="$Data.rules" label-width="100px"
|
|
3
|
+
<TForm :data="$Data.formData" :rules="$Data.rules" label-width="100px" ref="formRef">
|
|
4
4
|
<TFormItem label="字典类型" name="typeCode">
|
|
5
5
|
<TSelect v-model="$Data.formData.typeCode" placeholder="请选择字典类型" filterable>
|
|
6
6
|
<TOption v-for="item in typeList" :key="item.code" :value="item.code" :label="item.name" />
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
</template>
|
|
24
24
|
|
|
25
25
|
<script setup lang="ts">
|
|
26
|
-
import { computed } from "vue";
|
|
26
|
+
import { computed, reactive, ref } from "vue";
|
|
27
27
|
|
|
28
28
|
import { Form as TForm, FormItem as TFormItem, Input as TInput, Select as TSelect, Option as TOption, Textarea as TTextarea, InputNumber as TInputNumber, MessagePlugin } from "tdesign-vue-next";
|
|
29
29
|
import PageDialog from "@/components/pageDialog.vue";
|
|
@@ -46,11 +46,13 @@ const visible = computed({
|
|
|
46
46
|
set: (val) => $Emit("update:modelValue", val)
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
49
|
+
type TDesignFormInstance = {
|
|
50
|
+
validate: () => Promise<unknown>;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const formRef = ref<TDesignFormInstance | null>(null);
|
|
52
54
|
|
|
53
|
-
const $Data =
|
|
55
|
+
const $Data = reactive({
|
|
54
56
|
formData: {
|
|
55
57
|
typeCode: "",
|
|
56
58
|
key: "",
|
|
@@ -67,7 +69,13 @@ const $Data = $ref({
|
|
|
67
69
|
|
|
68
70
|
async function handleSubmit(): Promise<void> {
|
|
69
71
|
try {
|
|
70
|
-
const
|
|
72
|
+
const form = formRef.value;
|
|
73
|
+
if (!form) {
|
|
74
|
+
MessagePlugin.warning("表单未就绪");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const valid = await form.validate();
|
|
71
79
|
if (valid !== true) return;
|
|
72
80
|
const apiUrl = props.actionType === "add" ? "/addon/admin/dict/ins" : "/addon/admin/dict/upd";
|
|
73
81
|
const params: Record<string, unknown> = {
|
|
@@ -90,7 +98,7 @@ async function handleSubmit(): Promise<void> {
|
|
|
90
98
|
} else {
|
|
91
99
|
MessagePlugin.error(res.msg || "操作失败");
|
|
92
100
|
}
|
|
93
|
-
} catch (
|
|
101
|
+
} catch (_error) {
|
|
94
102
|
MessagePlugin.error("操作失败");
|
|
95
103
|
}
|
|
96
104
|
}
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
</template>
|
|
51
51
|
|
|
52
52
|
<script setup lang="ts">
|
|
53
|
-
import { onMounted } from "vue";
|
|
53
|
+
import { onMounted, reactive } from "vue";
|
|
54
54
|
|
|
55
55
|
import { Button as TButton, Dropdown as TDropdown, DropdownItem as TDropdownItem, DropdownMenu as TDropdownMenu, Input as TInput, Option as TOption, Select as TSelect, MessagePlugin } from "tdesign-vue-next";
|
|
56
56
|
import ILucidePlus from "~icons/lucide/plus";
|
|
@@ -64,7 +64,7 @@ import { $Http } from "@/plugins/http";
|
|
|
64
64
|
import PagedTableDetail from "@/components/pagedTableDetail.vue";
|
|
65
65
|
import { withDefaultColumns } from "befly-shared/utils/withDefaultColumns";
|
|
66
66
|
|
|
67
|
-
const $Data =
|
|
67
|
+
const $Data = reactive({
|
|
68
68
|
typeList: [],
|
|
69
69
|
searchTypeCode: "",
|
|
70
70
|
searchKeyword: "",
|
|
@@ -128,7 +128,7 @@ async function apiDictTypeAll(): Promise<void> {
|
|
|
128
128
|
}
|
|
129
129
|
);
|
|
130
130
|
$Data.typeList = res.data.lists || [];
|
|
131
|
-
} catch (
|
|
131
|
+
} catch (_error) {
|
|
132
132
|
MessagePlugin.error("加载数据失败");
|
|
133
133
|
}
|
|
134
134
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<PageDialog v-model="visible" :title="actionType === 'add' ? '添加字典类型' : '编辑字典类型'" @confirm="handleSubmit">
|
|
3
|
-
<TForm :data="$Data.formData" :rules="$Data.rules" label-width="100px"
|
|
3
|
+
<TForm :data="$Data.formData" :rules="$Data.rules" label-width="100px" ref="formRef">
|
|
4
4
|
<TFormItem label="类型代码" name="code">
|
|
5
5
|
<TInput v-model="$Data.formData.code" placeholder="请输入类型代码(英文/数字/下划线)" :disabled="actionType === 'upd'" />
|
|
6
6
|
</TFormItem>
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
</template>
|
|
19
19
|
|
|
20
20
|
<script setup lang="ts">
|
|
21
|
-
import { computed } from "vue";
|
|
21
|
+
import { computed, reactive, ref } from "vue";
|
|
22
22
|
|
|
23
23
|
import { Form as TForm, FormItem as TFormItem, Input as TInput, Textarea as TTextarea, InputNumber as TInputNumber, MessagePlugin } from "tdesign-vue-next";
|
|
24
24
|
import PageDialog from "@/components/pageDialog.vue";
|
|
@@ -40,11 +40,13 @@ const visible = computed({
|
|
|
40
40
|
set: (val) => $Emit("update:modelValue", val)
|
|
41
41
|
});
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
43
|
+
type TDesignFormInstance = {
|
|
44
|
+
validate: () => Promise<unknown>;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const formRef = ref<TDesignFormInstance | null>(null);
|
|
46
48
|
|
|
47
|
-
const $Data =
|
|
49
|
+
const $Data = reactive({
|
|
48
50
|
formData: {
|
|
49
51
|
code: "",
|
|
50
52
|
name: "",
|
|
@@ -58,7 +60,13 @@ const $Data = $ref({
|
|
|
58
60
|
});
|
|
59
61
|
|
|
60
62
|
async function handleSubmit(): Promise<void> {
|
|
61
|
-
const
|
|
63
|
+
const form = formRef.value;
|
|
64
|
+
if (!form) {
|
|
65
|
+
MessagePlugin.warning("表单未就绪");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const valid = await form.validate();
|
|
62
70
|
if (valid !== true) return;
|
|
63
71
|
|
|
64
72
|
try {
|
|
@@ -82,7 +90,7 @@ async function handleSubmit(): Promise<void> {
|
|
|
82
90
|
} else {
|
|
83
91
|
MessagePlugin.error(res.msg || "操作失败");
|
|
84
92
|
}
|
|
85
|
-
} catch (
|
|
93
|
+
} catch (_error) {
|
|
86
94
|
MessagePlugin.error("操作失败");
|
|
87
95
|
}
|
|
88
96
|
}
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
</template>
|
|
48
48
|
|
|
49
49
|
<script setup lang="ts">
|
|
50
|
+
import { reactive } from "vue";
|
|
50
51
|
import { Button as TButton, Dropdown as TDropdown, DropdownItem as TDropdownItem, DropdownMenu as TDropdownMenu, Input as TInput } from "tdesign-vue-next";
|
|
51
52
|
import ILucidePlus from "~icons/lucide/plus";
|
|
52
53
|
import ILucideRotateCw from "~icons/lucide/rotate-cw";
|
|
@@ -58,7 +59,7 @@ import EditDialog from "./components/edit.vue";
|
|
|
58
59
|
import PagedTableDetail from "@/components/pagedTableDetail.vue";
|
|
59
60
|
import { withDefaultColumns } from "befly-shared/utils/withDefaultColumns";
|
|
60
61
|
|
|
61
|
-
const $Data =
|
|
62
|
+
const $Data = reactive({
|
|
62
63
|
searchKeyword: "",
|
|
63
64
|
columns: withDefaultColumns([
|
|
64
65
|
{ colKey: "code", title: "类型代码" },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<PageDialog v-model="dialogVisible" :title="$Prop.actionType === 'upd' ? '编辑配置' : '添加配置'" :confirm-loading="$Data.submitting" @confirm="onSubmit">
|
|
3
|
-
<TForm :model="$Data.formData" label-width="120px" label-position="left" :rules="$Data2.formRules"
|
|
3
|
+
<TForm :model="$Data.formData" label-width="120px" label-position="left" :rules="$Data2.formRules" ref="formRef">
|
|
4
4
|
<TFormItem label="配置名称" prop="name">
|
|
5
5
|
<TInput v-model="$Data.formData.name" placeholder="请输入配置名称" :disabled="$Data.isSystem" />
|
|
6
6
|
</TFormItem>
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
</template>
|
|
42
42
|
|
|
43
43
|
<script setup lang="ts">
|
|
44
|
-
import { computed } from "vue";
|
|
44
|
+
import { computed, reactive, ref } from "vue";
|
|
45
45
|
|
|
46
46
|
import { Form as TForm, FormItem as TFormItem, Input as TInput, Textarea as TTextarea, InputNumber as TInputNumber, Select as TSelect, Option as TOption, RadioGroup as TRadioGroup, Radio as TRadio, MessagePlugin } from "tdesign-vue-next";
|
|
47
47
|
import PageDialog from "@/components/pageDialog.vue";
|
|
@@ -72,9 +72,11 @@ type PageDialogEventContext = {
|
|
|
72
72
|
};
|
|
73
73
|
|
|
74
74
|
// 表单引用
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
75
|
+
type TDesignFormInstance = {
|
|
76
|
+
validate: () => Promise<unknown>;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const formRef = ref<TDesignFormInstance | null>(null);
|
|
78
80
|
|
|
79
81
|
const dialogVisible = computed({
|
|
80
82
|
get: () => $Prop.modelValue,
|
|
@@ -83,7 +85,7 @@ const dialogVisible = computed({
|
|
|
83
85
|
}
|
|
84
86
|
});
|
|
85
87
|
|
|
86
|
-
const $Data =
|
|
88
|
+
const $Data = reactive({
|
|
87
89
|
submitting: false,
|
|
88
90
|
isSystem: false,
|
|
89
91
|
formData: {
|
|
@@ -99,7 +101,7 @@ const $Data = $ref({
|
|
|
99
101
|
}
|
|
100
102
|
});
|
|
101
103
|
|
|
102
|
-
const $Data2 =
|
|
104
|
+
const $Data2 = reactive({
|
|
103
105
|
formRules: {
|
|
104
106
|
name: [{ required: true, message: "请输入配置名称", trigger: "blur" }],
|
|
105
107
|
code: [
|
|
@@ -146,7 +148,13 @@ function onShow(): void {
|
|
|
146
148
|
}
|
|
147
149
|
|
|
148
150
|
async function onSubmit(context?: PageDialogEventContext): Promise<void> {
|
|
149
|
-
const
|
|
151
|
+
const form = formRef.value;
|
|
152
|
+
if (!form) {
|
|
153
|
+
MessagePlugin.warning("表单未就绪");
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const valid = await form.validate();
|
|
150
158
|
if (valid !== true) return;
|
|
151
159
|
|
|
152
160
|
$Data.submitting = true;
|
|
@@ -163,7 +171,7 @@ async function onSubmit(context?: PageDialogEventContext): Promise<void> {
|
|
|
163
171
|
} else {
|
|
164
172
|
MessagePlugin.error(res.msg || "操作失败");
|
|
165
173
|
}
|
|
166
|
-
} catch (
|
|
174
|
+
} catch (_error) {
|
|
167
175
|
MessagePlugin.error("操作失败");
|
|
168
176
|
} finally {
|
|
169
177
|
$Data.submitting = false;
|
|
@@ -75,6 +75,7 @@
|
|
|
75
75
|
</template>
|
|
76
76
|
|
|
77
77
|
<script setup lang="ts">
|
|
78
|
+
import { reactive } from "vue";
|
|
78
79
|
import { Button as TButton, Dropdown as TDropdown, DropdownItem as TDropdownItem, DropdownMenu as TDropdownMenu, Option as TOption, Select as TSelect, Tag as TTag } from "tdesign-vue-next";
|
|
79
80
|
import ILucidePlus from "~icons/lucide/plus";
|
|
80
81
|
import ILucideRotateCw from "~icons/lucide/rotate-cw";
|
|
@@ -87,7 +88,7 @@ import PagedTableDetail from "@/components/pagedTableDetail.vue";
|
|
|
87
88
|
import { withDefaultColumns } from "befly-shared/utils/withDefaultColumns";
|
|
88
89
|
|
|
89
90
|
// 响应式数据
|
|
90
|
-
const $Data =
|
|
91
|
+
const $Data = reactive({
|
|
91
92
|
columns: withDefaultColumns([
|
|
92
93
|
{ colKey: "name", title: "配置名称", fixed: "left", width: 150 },
|
|
93
94
|
{ colKey: "code", title: "配置代码", ellipsis: true },
|
|
@@ -24,10 +24,18 @@
|
|
|
24
24
|
</template>
|
|
25
25
|
|
|
26
26
|
<script setup lang="ts">
|
|
27
|
+
import { reactive } from "vue";
|
|
27
28
|
import { $Http } from "@/plugins/http";
|
|
28
29
|
|
|
30
|
+
type AddonListItem = {
|
|
31
|
+
name: string;
|
|
32
|
+
title: string;
|
|
33
|
+
version: string;
|
|
34
|
+
description: string;
|
|
35
|
+
};
|
|
36
|
+
|
|
29
37
|
// 组件内部数据
|
|
30
|
-
const addonList =
|
|
38
|
+
const addonList = reactive<AddonListItem[]>([]);
|
|
31
39
|
|
|
32
40
|
// 获取数据
|
|
33
41
|
const fetchData = async () => {
|
|
@@ -40,7 +48,7 @@ const fetchData = async () => {
|
|
|
40
48
|
}
|
|
41
49
|
);
|
|
42
50
|
addonList.splice(0, addonList.length, ...data);
|
|
43
|
-
} catch (
|
|
51
|
+
} catch (_error) {
|
|
44
52
|
// 静默失败:不阻断页面展示
|
|
45
53
|
}
|
|
46
54
|
};
|
|
@@ -36,11 +36,21 @@
|
|
|
36
36
|
</template>
|
|
37
37
|
|
|
38
38
|
<script setup lang="ts">
|
|
39
|
+
import { reactive } from "vue";
|
|
39
40
|
import ILucideServer from "~icons/lucide/server";
|
|
40
41
|
import { $Http } from "@/plugins/http";
|
|
41
42
|
|
|
43
|
+
type EnvironmentInfo = {
|
|
44
|
+
os: string;
|
|
45
|
+
server: string;
|
|
46
|
+
nodeVersion: string;
|
|
47
|
+
database: string;
|
|
48
|
+
cache: string;
|
|
49
|
+
timezone: string;
|
|
50
|
+
};
|
|
51
|
+
|
|
42
52
|
// 组件内部数据
|
|
43
|
-
const environmentInfo =
|
|
53
|
+
const environmentInfo = reactive<EnvironmentInfo>({
|
|
44
54
|
os: "",
|
|
45
55
|
server: "",
|
|
46
56
|
nodeVersion: "",
|
|
@@ -60,7 +70,7 @@ const fetchData = async () => {
|
|
|
60
70
|
}
|
|
61
71
|
);
|
|
62
72
|
Object.assign(environmentInfo, data);
|
|
63
|
-
} catch (
|
|
73
|
+
} catch (_error) {
|
|
64
74
|
// 静默失败:不阻断页面展示
|
|
65
75
|
}
|
|
66
76
|
};
|
|
@@ -34,8 +34,22 @@
|
|
|
34
34
|
</template>
|
|
35
35
|
|
|
36
36
|
<script setup lang="ts">
|
|
37
|
+
import { reactive } from "vue";
|
|
38
|
+
|
|
39
|
+
type OperationLogStatus = "success" | "failed";
|
|
40
|
+
|
|
41
|
+
type OperationLogItem = {
|
|
42
|
+
id: number;
|
|
43
|
+
userName: string;
|
|
44
|
+
action: string;
|
|
45
|
+
module: string;
|
|
46
|
+
ip: string;
|
|
47
|
+
status: OperationLogStatus;
|
|
48
|
+
createdAt: number;
|
|
49
|
+
};
|
|
50
|
+
|
|
37
51
|
// 组件内部数据
|
|
38
|
-
const operationLogs =
|
|
52
|
+
const operationLogs = reactive<OperationLogItem[]>([
|
|
39
53
|
{ id: 1, userName: "管理员", action: "创建角色", module: "权限管理", ip: "192.168.1.100", status: "success", createdAt: Date.now() - 120000 },
|
|
40
54
|
{ id: 2, userName: "张三", action: "修改菜单", module: "系统设置", ip: "192.168.1.101", status: "success", createdAt: Date.now() - 900000 },
|
|
41
55
|
{ id: 3, userName: "李四", action: "删除接口", module: "接口管理", ip: "192.168.1.102", status: "failed", createdAt: Date.now() - 3600000 },
|
|
@@ -43,7 +57,7 @@ const operationLogs = $ref([
|
|
|
43
57
|
{ id: 5, userName: "王五", action: "登录系统", module: "系统", ip: "192.168.1.103", status: "success", createdAt: Date.now() - 10800000 }
|
|
44
58
|
]);
|
|
45
59
|
|
|
46
|
-
const formatTime = (timestamp) => {
|
|
60
|
+
const formatTime = (timestamp: number): string => {
|
|
47
61
|
const date = new Date(timestamp);
|
|
48
62
|
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
49
63
|
const day = String(date.getDate()).padStart(2, "0");
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
</template>
|
|
54
54
|
|
|
55
55
|
<script setup lang="ts">
|
|
56
|
+
import { reactive } from "vue";
|
|
56
57
|
import ILucideActivity from "~icons/lucide/activity";
|
|
57
58
|
import ILucideClock from "~icons/lucide/clock";
|
|
58
59
|
import ILucideTrendingUp from "~icons/lucide/trending-up";
|
|
@@ -60,13 +61,18 @@ import ILucideAlertCircle from "~icons/lucide/alert-circle";
|
|
|
60
61
|
import ILucideAlertTriangle from "~icons/lucide/alert-triangle";
|
|
61
62
|
import { $Http } from "@/plugins/http";
|
|
62
63
|
|
|
64
|
+
type SlowestApiInfo = {
|
|
65
|
+
path: string;
|
|
66
|
+
time: number;
|
|
67
|
+
};
|
|
68
|
+
|
|
63
69
|
// 组件内部数据
|
|
64
|
-
const performanceMetrics =
|
|
70
|
+
const performanceMetrics = reactive({
|
|
65
71
|
avgResponseTime: 0,
|
|
66
72
|
qps: 0,
|
|
67
73
|
errorRate: 0,
|
|
68
74
|
activeConnections: 0,
|
|
69
|
-
slowestApi: null
|
|
75
|
+
slowestApi: null as SlowestApiInfo | null
|
|
70
76
|
});
|
|
71
77
|
|
|
72
78
|
// 获取数据
|
|
@@ -80,7 +86,7 @@ const fetchData = async () => {
|
|
|
80
86
|
}
|
|
81
87
|
);
|
|
82
88
|
Object.assign(performanceMetrics, data);
|
|
83
|
-
} catch (
|
|
89
|
+
} catch (_error) {
|
|
84
90
|
// 静默失败:不阻断页面展示
|
|
85
91
|
}
|
|
86
92
|
};
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
</template>
|
|
36
36
|
|
|
37
37
|
<script setup lang="ts">
|
|
38
|
+
import { reactive } from "vue";
|
|
38
39
|
import ILucideCheckCircle from "~icons/lucide/check-circle";
|
|
39
40
|
import ILucideDatabase from "~icons/lucide/database";
|
|
40
41
|
import ILucideZap from "~icons/lucide/zap";
|
|
@@ -46,8 +47,14 @@ import ILucideXCircle from "~icons/lucide/x-circle";
|
|
|
46
47
|
import ILucideAlertCircle from "~icons/lucide/alert-circle";
|
|
47
48
|
import { $Http } from "@/plugins/http";
|
|
48
49
|
|
|
50
|
+
type ServiceStatusItem = {
|
|
51
|
+
name: string;
|
|
52
|
+
status: string;
|
|
53
|
+
responseTime?: string;
|
|
54
|
+
};
|
|
55
|
+
|
|
49
56
|
// 组件内部数据
|
|
50
|
-
const services =
|
|
57
|
+
const services = reactive<ServiceStatusItem[]>([]);
|
|
51
58
|
|
|
52
59
|
// 获取数据
|
|
53
60
|
const fetchData = async () => {
|
|
@@ -60,7 +67,7 @@ const fetchData = async () => {
|
|
|
60
67
|
}
|
|
61
68
|
);
|
|
62
69
|
services.splice(0, services.length, ...data.services);
|
|
63
|
-
} catch (
|
|
70
|
+
} catch (_error) {
|
|
64
71
|
// 静默失败:不阻断页面展示
|
|
65
72
|
}
|
|
66
73
|
};
|
|
@@ -68,7 +75,7 @@ const fetchData = async () => {
|
|
|
68
75
|
fetchData();
|
|
69
76
|
|
|
70
77
|
// 工具函数
|
|
71
|
-
const getStatusColor = (status) => {
|
|
78
|
+
const getStatusColor = (status: string): string => {
|
|
72
79
|
const colors = {
|
|
73
80
|
running: "success",
|
|
74
81
|
stopped: "error",
|
|
@@ -77,7 +84,7 @@ const getStatusColor = (status) => {
|
|
|
77
84
|
return colors[status] || "default";
|
|
78
85
|
};
|
|
79
86
|
|
|
80
|
-
const getStatusText = (status) => {
|
|
87
|
+
const getStatusText = (status: string): string => {
|
|
81
88
|
const texts = {
|
|
82
89
|
running: "正常",
|
|
83
90
|
stopped: "停止",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
</template>
|
|
27
27
|
|
|
28
28
|
<script setup lang="ts">
|
|
29
|
+
import { reactive } from "vue";
|
|
29
30
|
import { Tag as TTag } from "tdesign-vue-next";
|
|
30
31
|
import ILucideBell from "~icons/lucide/bell";
|
|
31
32
|
import ILucideInfo from "~icons/lucide/info";
|
|
@@ -33,15 +34,25 @@ import ILucideCheckCircle from "~icons/lucide/check-circle";
|
|
|
33
34
|
import ILucideAlertTriangle from "~icons/lucide/alert-triangle";
|
|
34
35
|
import ILucideXCircle from "~icons/lucide/x-circle";
|
|
35
36
|
|
|
37
|
+
type NotificationType = "info" | "success" | "warning" | "error" | "other";
|
|
38
|
+
|
|
39
|
+
type NotificationItem = {
|
|
40
|
+
id: number;
|
|
41
|
+
type: NotificationType;
|
|
42
|
+
title: string;
|
|
43
|
+
isRead: boolean;
|
|
44
|
+
createdAt: number;
|
|
45
|
+
};
|
|
46
|
+
|
|
36
47
|
// 组件内部数据
|
|
37
|
-
const notifications =
|
|
48
|
+
const notifications = reactive<NotificationItem[]>([
|
|
38
49
|
{ id: 1, type: "warning", title: "系统更新提醒 - v1.1.0 版本已发布", isRead: false, createdAt: Date.now() - 3600000 },
|
|
39
50
|
{ id: 2, type: "info", title: "数据备份完成 - 今日凌晨自动备份成功", isRead: true, createdAt: Date.now() - 21600000 },
|
|
40
51
|
{ id: 3, type: "error", title: "SSL证书即将过期 - 请及时更新证书", isRead: false, createdAt: Date.now() - 86400000 },
|
|
41
52
|
{ id: 4, type: "success", title: "性能优化完成 - 响应速度提升30%", isRead: true, createdAt: Date.now() - 172800000 }
|
|
42
53
|
]);
|
|
43
54
|
|
|
44
|
-
const formatTime = (timestamp) => {
|
|
55
|
+
const formatTime = (timestamp: number): string => {
|
|
45
56
|
const date = new Date(timestamp);
|
|
46
57
|
const now = Date.now();
|
|
47
58
|
const diff = now - timestamp;
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
</template>
|
|
36
36
|
|
|
37
37
|
<script setup lang="ts">
|
|
38
|
+
import { reactive } from "vue";
|
|
38
39
|
import ILucideInfo from "~icons/lucide/info";
|
|
39
40
|
import ILucideMenu from "~icons/lucide/menu";
|
|
40
41
|
import ILucideWebhook from "~icons/lucide/webhook";
|
|
@@ -42,7 +43,7 @@ import ILucideUsers from "~icons/lucide/users";
|
|
|
42
43
|
import { $Http } from "@/plugins/http";
|
|
43
44
|
|
|
44
45
|
// 组件内部数据
|
|
45
|
-
const permissionStats =
|
|
46
|
+
const permissionStats = reactive({
|
|
46
47
|
menuCount: 0,
|
|
47
48
|
apiCount: 0,
|
|
48
49
|
roleCount: 0
|
|
@@ -59,7 +60,7 @@ const fetchData = async () => {
|
|
|
59
60
|
}
|
|
60
61
|
);
|
|
61
62
|
Object.assign(permissionStats, data);
|
|
62
|
-
} catch (
|
|
63
|
+
} catch (_error) {
|
|
63
64
|
// 静默失败:不阻断页面展示
|
|
64
65
|
}
|
|
65
66
|
};
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
</template>
|
|
40
40
|
|
|
41
41
|
<script setup lang="ts">
|
|
42
|
+
import { reactive } from "vue";
|
|
42
43
|
import { Progress as TProgress } from "tdesign-vue-next";
|
|
43
44
|
import ILucideActivity from "~icons/lucide/activity";
|
|
44
45
|
import ILucideCpu from "~icons/lucide/cpu";
|
|
@@ -46,8 +47,14 @@ import ILucideHardDrive from "~icons/lucide/hard-drive";
|
|
|
46
47
|
import ILucideDisc from "~icons/lucide/disc";
|
|
47
48
|
import { $Http } from "@/plugins/http";
|
|
48
49
|
|
|
50
|
+
type SystemResourcesInfo = {
|
|
51
|
+
cpu: { usage: number; cores: number };
|
|
52
|
+
memory: { used: number; total: number; percentage: number };
|
|
53
|
+
disk: { used: number; total: number; percentage: number };
|
|
54
|
+
};
|
|
55
|
+
|
|
49
56
|
// 组件内部数据
|
|
50
|
-
const systemResources =
|
|
57
|
+
const systemResources = reactive<SystemResourcesInfo>({
|
|
51
58
|
cpu: { usage: 0, cores: 0 },
|
|
52
59
|
memory: { used: 0, total: 0, percentage: 0 },
|
|
53
60
|
disk: { used: 0, total: 0, percentage: 0 }
|
|
@@ -64,7 +71,7 @@ const fetchData = async () => {
|
|
|
64
71
|
}
|
|
65
72
|
);
|
|
66
73
|
Object.assign(systemResources, data);
|
|
67
|
-
} catch (
|
|
74
|
+
} catch (_error) {
|
|
68
75
|
// 静默失败:不阻断页面展示
|
|
69
76
|
}
|
|
70
77
|
};
|
|
@@ -72,7 +79,7 @@ const fetchData = async () => {
|
|
|
72
79
|
fetchData();
|
|
73
80
|
|
|
74
81
|
// 工具函数
|
|
75
|
-
const getProgressColor = (percentage) => {
|
|
82
|
+
const getProgressColor = (percentage: number): string => {
|
|
76
83
|
if (percentage < 50) return "success";
|
|
77
84
|
if (percentage < 80) return "warning";
|
|
78
85
|
return "danger";
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
</template>
|
|
40
40
|
|
|
41
41
|
<script setup lang="ts">
|
|
42
|
+
import { reactive } from "vue";
|
|
42
43
|
import { Button as TButton, MessagePlugin } from "tdesign-vue-next";
|
|
43
44
|
import ILucideUser from "~icons/lucide/user";
|
|
44
45
|
import ILucideMail from "~icons/lucide/mail";
|
|
@@ -47,9 +48,22 @@ import ILucideClock from "~icons/lucide/clock";
|
|
|
47
48
|
import ILucideRotateCw from "~icons/lucide/rotate-cw";
|
|
48
49
|
import { $Http } from "@/plugins/http";
|
|
49
50
|
|
|
51
|
+
type UserInfo = {
|
|
52
|
+
nickname?: string;
|
|
53
|
+
name?: string;
|
|
54
|
+
username?: string;
|
|
55
|
+
role?: {
|
|
56
|
+
name?: string;
|
|
57
|
+
};
|
|
58
|
+
roleCode?: string;
|
|
59
|
+
email?: string;
|
|
60
|
+
phone?: string;
|
|
61
|
+
lastLoginTime?: number | string;
|
|
62
|
+
};
|
|
63
|
+
|
|
50
64
|
// 响应式数据
|
|
51
|
-
const $Data =
|
|
52
|
-
userInfo: {},
|
|
65
|
+
const $Data = reactive({
|
|
66
|
+
userInfo: {} as UserInfo,
|
|
53
67
|
refreshing: false
|
|
54
68
|
});
|
|
55
69
|
|
|
@@ -62,8 +76,8 @@ async function fetchData(): Promise<void> {
|
|
|
62
76
|
dropValues: [""]
|
|
63
77
|
}
|
|
64
78
|
);
|
|
65
|
-
Object.assign($Data.userInfo, data);
|
|
66
|
-
} catch (
|
|
79
|
+
Object.assign($Data.userInfo, data as UserInfo);
|
|
80
|
+
} catch (_error) {
|
|
67
81
|
MessagePlugin.error("获取用户信息失败");
|
|
68
82
|
}
|
|
69
83
|
}
|
|
@@ -93,7 +107,7 @@ async function handleRefreshCache(): Promise<void> {
|
|
|
93
107
|
} else {
|
|
94
108
|
MessagePlugin.warning(result.msg || "部分缓存刷新失败");
|
|
95
109
|
}
|
|
96
|
-
} catch (
|
|
110
|
+
} catch (_error) {
|
|
97
111
|
MessagePlugin.error("刷新缓存失败,请稍后重试");
|
|
98
112
|
} finally {
|
|
99
113
|
$Data.refreshing = false;
|