befly-admin-ui 1.8.14
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/LICENSE +201 -0
- package/README.md +188 -0
- package/jsconfig.json +14 -0
- package/package.json +51 -0
- package/styles/variables.scss +148 -0
- package/utils/arrayToTree.js +115 -0
- package/utils/cleanParams.js +29 -0
- package/utils/fieldClear.js +62 -0
- package/utils/genShortId.js +12 -0
- package/utils/hashPassword.js +9 -0
- package/utils/scanViewsDir.js +120 -0
- package/utils/withDefaultColumns.js +46 -0
- package/views/config/dict/components/edit.vue +120 -0
- package/views/config/dict/index.vue +188 -0
- package/views/config/dictType/components/edit.vue +110 -0
- package/views/config/dictType/index.vue +153 -0
- package/views/config/index.vue +3 -0
- package/views/config/system/components/edit.vue +184 -0
- package/views/config/system/index.vue +188 -0
- package/views/index/components/addonList.vue +148 -0
- package/views/index/components/environmentInfo.vue +116 -0
- package/views/index/components/operationLogs.vue +127 -0
- package/views/index/components/performanceMetrics.vue +153 -0
- package/views/index/components/quickActions.vue +30 -0
- package/views/index/components/serviceStatus.vue +197 -0
- package/views/index/components/systemNotifications.vue +144 -0
- package/views/index/components/systemOverview.vue +194 -0
- package/views/index/components/systemResources.vue +121 -0
- package/views/index/components/userInfo.vue +210 -0
- package/views/index/index.vue +67 -0
- package/views/jsconfig.json +15 -0
- package/views/log/email/index.vue +221 -0
- package/views/log/index.vue +3 -0
- package/views/log/login/index.vue +95 -0
- package/views/log/operate/index.vue +169 -0
- package/views/login_1/index.vue +400 -0
- package/views/people/admin/components/edit.vue +173 -0
- package/views/people/admin/index.vue +121 -0
- package/views/people/index.vue +3 -0
- package/views/permission/api/index.vue +146 -0
- package/views/permission/index.vue +3 -0
- package/views/permission/menu/index.vue +109 -0
- package/views/permission/role/components/api.vue +371 -0
- package/views/permission/role/components/edit.vue +143 -0
- package/views/permission/role/components/menu.vue +310 -0
- package/views/permission/role/index.vue +175 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<PagedTableDetail class="page-dict page-table" :columns="$Data.columns" :endpoints="$Data.endpoints">
|
|
3
|
+
<template #toolLeft>
|
|
4
|
+
<TButton theme="primary" @click="onAdd">
|
|
5
|
+
<template #icon>
|
|
6
|
+
<AddIcon />
|
|
7
|
+
</template>
|
|
8
|
+
</TButton>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<template #toolRight="scope">
|
|
12
|
+
<TSelect v-model="$Data.searchTypeCode" placeholder="请选择字典类型" clearable filterable @change="handleSearch(scope.reload)">
|
|
13
|
+
<TOption v-for="item in $Data.typeList" :key="item.code" :value="item.code" :label="item.name" />
|
|
14
|
+
</TSelect>
|
|
15
|
+
<TInput v-model="$Data.searchKeyword" placeholder="搜索键/标签" clearable @enter="handleSearch(scope.reload)" @clear="handleSearch(scope.reload)">
|
|
16
|
+
<template #suffix-icon>
|
|
17
|
+
<SearchIcon />
|
|
18
|
+
</template>
|
|
19
|
+
</TInput>
|
|
20
|
+
<TButton shape="circle" @click="handleRefresh(scope.reload)">
|
|
21
|
+
<template #icon>
|
|
22
|
+
<RefreshIcon />
|
|
23
|
+
</template>
|
|
24
|
+
</TButton>
|
|
25
|
+
</template>
|
|
26
|
+
|
|
27
|
+
<template #operation="{ row, deleteRow }">
|
|
28
|
+
<TDropdown trigger="click" placement="bottom-right" @click="onDropdownAction($event, row, deleteRow)">
|
|
29
|
+
<TButton theme="primary" size="small">
|
|
30
|
+
操作
|
|
31
|
+
<template #suffix><ChevronDownIcon /></template>
|
|
32
|
+
</TButton>
|
|
33
|
+
<TDropdownMenu slot="dropdown">
|
|
34
|
+
<TDropdownItem value="upd">
|
|
35
|
+
<EditIcon />
|
|
36
|
+
编辑
|
|
37
|
+
</TDropdownItem>
|
|
38
|
+
<TDropdownItem value="del" :divider="true">
|
|
39
|
+
<DeleteIcon style="width: 14px; height: 14px; margin-right: 6px" />
|
|
40
|
+
删除
|
|
41
|
+
</TDropdownItem>
|
|
42
|
+
</TDropdownMenu>
|
|
43
|
+
</TDropdown>
|
|
44
|
+
</template>
|
|
45
|
+
|
|
46
|
+
<template #dialogs="scope">
|
|
47
|
+
<EditDialog v-if="$Data.editVisible" v-model="$Data.editVisible" :action-type="$Data.actionType" :row-data="$Data.rowData" :type-list="$Data.typeList" @success="onDialogSuccess(scope.reload)" />
|
|
48
|
+
</template>
|
|
49
|
+
</PagedTableDetail>
|
|
50
|
+
</template>
|
|
51
|
+
|
|
52
|
+
<script setup lang="ts">
|
|
53
|
+
import { onMounted, reactive } from "vue";
|
|
54
|
+
|
|
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
|
+
import { AddIcon, ChevronDownIcon, DeleteIcon, EditIcon, RefreshIcon, SearchIcon } from "tdesign-icons-vue-next";
|
|
57
|
+
import EditDialog from "./components/edit.vue";
|
|
58
|
+
import { $Http } from "@/plugins/http";
|
|
59
|
+
import PagedTableDetail from "@/components/pagedTableDetail.vue";
|
|
60
|
+
import { withDefaultColumns } from "befly-admin-ui/utils/withDefaultColumns";
|
|
61
|
+
|
|
62
|
+
const $Data = reactive({
|
|
63
|
+
typeList: [],
|
|
64
|
+
searchTypeCode: "",
|
|
65
|
+
searchKeyword: "",
|
|
66
|
+
columns: withDefaultColumns([
|
|
67
|
+
{ colKey: "typeName", title: "类型名称" },
|
|
68
|
+
{ colKey: "typeCode", title: "类型代码" },
|
|
69
|
+
{ colKey: "label", title: "标签" },
|
|
70
|
+
{ colKey: "key", title: "键值" },
|
|
71
|
+
{ colKey: "sort", title: "排序", width: 100 },
|
|
72
|
+
{ colKey: "remark", title: "备注" },
|
|
73
|
+
{ colKey: "operation", title: "操作" }
|
|
74
|
+
]),
|
|
75
|
+
endpoints: {
|
|
76
|
+
list: {
|
|
77
|
+
path: "/core/dict/list",
|
|
78
|
+
dropValues: [""],
|
|
79
|
+
buildData: () => {
|
|
80
|
+
return {
|
|
81
|
+
typeCode: $Data.searchTypeCode,
|
|
82
|
+
keyword: $Data.searchKeyword
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
delete: {
|
|
87
|
+
path: "/core/dict/del",
|
|
88
|
+
idKey: "id",
|
|
89
|
+
confirm: (row) => {
|
|
90
|
+
return {
|
|
91
|
+
header: "确认删除",
|
|
92
|
+
body: `确认删除字典项“${row.label}”吗?`,
|
|
93
|
+
confirmBtn: "删除",
|
|
94
|
+
status: "warning"
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
editVisible: false,
|
|
100
|
+
actionType: "add",
|
|
101
|
+
rowData: {}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
function onAdd(): void {
|
|
105
|
+
onAction("add", {});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function onDialogSuccess(reload: (options: { keepSelection?: boolean }) => void): void {
|
|
109
|
+
reload({ keepSelection: true });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function initData(): Promise<void> {
|
|
113
|
+
await apiDictTypeAll();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async function apiDictTypeAll(): Promise<void> {
|
|
117
|
+
try {
|
|
118
|
+
const res = await $Http.post(
|
|
119
|
+
"/core/dictType/all",
|
|
120
|
+
{},
|
|
121
|
+
{
|
|
122
|
+
dropValues: [""]
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
$Data.typeList = res.data.lists || [];
|
|
126
|
+
} catch (_error) {
|
|
127
|
+
MessagePlugin.error("加载数据失败");
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function handleSearch(reload: (options: { keepSelection?: boolean; resetPage?: boolean }) => void): void {
|
|
132
|
+
reload({ keepSelection: false, resetPage: true });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function handleRefresh(reload: (options: { keepSelection?: boolean; resetPage?: boolean }) => void): void {
|
|
136
|
+
$Data.searchTypeCode = "";
|
|
137
|
+
$Data.searchKeyword = "";
|
|
138
|
+
reload({ keepSelection: false, resetPage: true });
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function onAction(type: string, row: Record<string, unknown>): void {
|
|
142
|
+
if (type === "add") {
|
|
143
|
+
$Data.actionType = "add";
|
|
144
|
+
$Data.rowData = {};
|
|
145
|
+
$Data.editVisible = true;
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (type === "upd") {
|
|
150
|
+
$Data.actionType = "upd";
|
|
151
|
+
$Data.rowData = Object.assign({}, row);
|
|
152
|
+
$Data.editVisible = true;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function onDropdownAction(data: unknown, row: Record<string, unknown>, deleteRow: (r: Record<string, unknown>) => void): void {
|
|
157
|
+
const record = data as Record<string, unknown>;
|
|
158
|
+
const rawValue = record && record["value"] ? record["value"] : "";
|
|
159
|
+
const cmd = rawValue ? String(rawValue) : "";
|
|
160
|
+
if (cmd === "del") {
|
|
161
|
+
deleteRow(row);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
onAction(cmd, row);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
onMounted(() => {
|
|
168
|
+
initData();
|
|
169
|
+
});
|
|
170
|
+
</script>
|
|
171
|
+
|
|
172
|
+
<style scoped lang="scss">
|
|
173
|
+
.page-dict {
|
|
174
|
+
.main-tool .right {
|
|
175
|
+
display: flex;
|
|
176
|
+
gap: 8px;
|
|
177
|
+
align-items: center;
|
|
178
|
+
|
|
179
|
+
.t-select {
|
|
180
|
+
width: 200px;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.t-input {
|
|
184
|
+
width: 240px;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
</style>
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<PageDialog v-model="visible" :title="actionType === 'add' ? '添加字典类型' : '编辑字典类型'" @confirm="handleSubmit">
|
|
3
|
+
<TForm :data="$Data.formData" :rules="$Data.rules" label-width="100px" ref="formRef">
|
|
4
|
+
<TFormItem label="类型代码" name="code">
|
|
5
|
+
<TInput v-model="$Data.formData.code" placeholder="请输入类型代码(英文/数字/下划线)" :disabled="actionType === 'upd'" />
|
|
6
|
+
</TFormItem>
|
|
7
|
+
<TFormItem label="类型名称" name="name">
|
|
8
|
+
<TInput v-model="$Data.formData.name" placeholder="请输入类型名称" />
|
|
9
|
+
</TFormItem>
|
|
10
|
+
<TFormItem label="描述" name="description">
|
|
11
|
+
<TTextarea v-model="$Data.formData.description" placeholder="请输入描述信息" :autosize="{ minRows: 3, maxRows: 6 }" />
|
|
12
|
+
</TFormItem>
|
|
13
|
+
<TFormItem label="排序" name="sort">
|
|
14
|
+
<TInputNumber v-model="$Data.formData.sort" :min="0" placeholder="请输入排序值" />
|
|
15
|
+
</TFormItem>
|
|
16
|
+
</TForm>
|
|
17
|
+
</PageDialog>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script setup lang="ts">
|
|
21
|
+
import { computed, reactive, ref } from "vue";
|
|
22
|
+
|
|
23
|
+
import { Form as TForm, FormItem as TFormItem, Input as TInput, Textarea as TTextarea, InputNumber as TInputNumber, MessagePlugin } from "tdesign-vue-next";
|
|
24
|
+
import PageDialog from "@/components/pageDialog.vue";
|
|
25
|
+
import { $Http } from "@/plugins/http";
|
|
26
|
+
|
|
27
|
+
const props = defineProps({
|
|
28
|
+
modelValue: Boolean,
|
|
29
|
+
actionType: String,
|
|
30
|
+
rowData: Object
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const $Emit = defineEmits<{
|
|
34
|
+
(e: "update:modelValue", value: boolean): void;
|
|
35
|
+
(e: "success"): void;
|
|
36
|
+
}>();
|
|
37
|
+
|
|
38
|
+
const visible = computed({
|
|
39
|
+
get: () => props.modelValue,
|
|
40
|
+
set: (val) => $Emit("update:modelValue", val)
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
type TDesignFormInstance = {
|
|
44
|
+
validate: () => Promise<unknown>;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const formRef = ref<TDesignFormInstance | null>(null);
|
|
48
|
+
|
|
49
|
+
const $Data = reactive({
|
|
50
|
+
formData: {
|
|
51
|
+
code: "",
|
|
52
|
+
name: "",
|
|
53
|
+
description: "",
|
|
54
|
+
sort: 0
|
|
55
|
+
},
|
|
56
|
+
rules: {
|
|
57
|
+
code: [{ required: true, message: "请输入类型代码" }],
|
|
58
|
+
name: [{ required: true, message: "请输入类型名称" }]
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
async function handleSubmit(): Promise<void> {
|
|
63
|
+
const form = formRef.value;
|
|
64
|
+
if (!form) {
|
|
65
|
+
MessagePlugin.warning("表单未就绪");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const valid = await form.validate();
|
|
70
|
+
if (valid !== true) return;
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const apiUrl = props.actionType === "add" ? "/core/dictType/ins" : "/core/dictType/upd";
|
|
74
|
+
const params: Record<string, unknown> = {
|
|
75
|
+
code: $Data.formData.code,
|
|
76
|
+
name: $Data.formData.name,
|
|
77
|
+
description: $Data.formData.description,
|
|
78
|
+
sort: $Data.formData.sort
|
|
79
|
+
};
|
|
80
|
+
if (props.actionType === "upd" && props.rowData) {
|
|
81
|
+
const row = props.rowData as Record<string, unknown>;
|
|
82
|
+
params["id"] = row["id"];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const res = await $Http.post(apiUrl, params);
|
|
86
|
+
if (res.code === 0) {
|
|
87
|
+
MessagePlugin.success(props.actionType === "add" ? "添加成功" : "更新成功");
|
|
88
|
+
visible.value = false;
|
|
89
|
+
$Emit("success");
|
|
90
|
+
} else {
|
|
91
|
+
MessagePlugin.error(res.msg || "操作失败");
|
|
92
|
+
}
|
|
93
|
+
} catch (_error) {
|
|
94
|
+
MessagePlugin.error("操作失败");
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 该组件由父组件 v-if 控制挂载/卸载,因此无需 watch:创建时初始化一次即可
|
|
99
|
+
if (props.actionType === "upd" && props.rowData) {
|
|
100
|
+
$Data.formData.code = props.rowData.code || "";
|
|
101
|
+
$Data.formData.name = props.rowData.name || "";
|
|
102
|
+
$Data.formData.description = props.rowData.description || "";
|
|
103
|
+
$Data.formData.sort = props.rowData.sort || 0;
|
|
104
|
+
} else {
|
|
105
|
+
$Data.formData.code = "";
|
|
106
|
+
$Data.formData.name = "";
|
|
107
|
+
$Data.formData.description = "";
|
|
108
|
+
$Data.formData.sort = 0;
|
|
109
|
+
}
|
|
110
|
+
</script>
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<PagedTableDetail class="page-dict-type page-table" :columns="$Data.columns" :endpoints="$Data.endpoints">
|
|
3
|
+
<template #toolLeft>
|
|
4
|
+
<TButton theme="primary" @click="onAdd">
|
|
5
|
+
<template #icon>
|
|
6
|
+
<AddIcon />
|
|
7
|
+
</template>
|
|
8
|
+
</TButton>
|
|
9
|
+
</template>
|
|
10
|
+
|
|
11
|
+
<template #toolRight="scope">
|
|
12
|
+
<TInput v-model="$Data.searchKeyword" placeholder="搜索类型名称" clearable @enter="handleSearch(scope.reload)" @clear="handleSearch(scope.reload)">
|
|
13
|
+
<template #suffix-icon>
|
|
14
|
+
<SearchIcon />
|
|
15
|
+
</template>
|
|
16
|
+
</TInput>
|
|
17
|
+
<TButton shape="circle" @click="handleRefresh(scope.reload)">
|
|
18
|
+
<template #icon>
|
|
19
|
+
<RefreshIcon />
|
|
20
|
+
</template>
|
|
21
|
+
</TButton>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<template #operation="{ row, deleteRow }">
|
|
25
|
+
<TDropdown trigger="click" placement="bottom-right" @click="onDropdownAction($event, row, deleteRow)">
|
|
26
|
+
<TButton theme="primary" size="small">
|
|
27
|
+
操作
|
|
28
|
+
<template #suffix><ChevronDownIcon /></template>
|
|
29
|
+
</TButton>
|
|
30
|
+
<TDropdownMenu slot="dropdown">
|
|
31
|
+
<TDropdownItem value="upd">
|
|
32
|
+
<EditIcon />
|
|
33
|
+
编辑
|
|
34
|
+
</TDropdownItem>
|
|
35
|
+
<TDropdownItem value="del" :divider="true">
|
|
36
|
+
<DeleteIcon style="width: 14px; height: 14px; margin-right: 6px" />
|
|
37
|
+
删除
|
|
38
|
+
</TDropdownItem>
|
|
39
|
+
</TDropdownMenu>
|
|
40
|
+
</TDropdown>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<template #dialogs="scope">
|
|
44
|
+
<EditDialog v-if="$Data.editVisible" v-model="$Data.editVisible" :action-type="$Data.actionType" :row-data="$Data.rowData" @success="onDialogSuccess(scope.reload)" />
|
|
45
|
+
</template>
|
|
46
|
+
</PagedTableDetail>
|
|
47
|
+
</template>
|
|
48
|
+
|
|
49
|
+
<script setup lang="ts">
|
|
50
|
+
import { reactive } from "vue";
|
|
51
|
+
import { Button as TButton, Dropdown as TDropdown, DropdownItem as TDropdownItem, DropdownMenu as TDropdownMenu, Input as TInput } from "tdesign-vue-next";
|
|
52
|
+
import { AddIcon, ChevronDownIcon, DeleteIcon, EditIcon, RefreshIcon, SearchIcon } from "tdesign-icons-vue-next";
|
|
53
|
+
import EditDialog from "./components/edit.vue";
|
|
54
|
+
import PagedTableDetail from "@/components/pagedTableDetail.vue";
|
|
55
|
+
import { withDefaultColumns } from "befly-admin-ui/utils/withDefaultColumns";
|
|
56
|
+
|
|
57
|
+
const $Data = reactive({
|
|
58
|
+
searchKeyword: "",
|
|
59
|
+
columns: withDefaultColumns([
|
|
60
|
+
{ colKey: "code", title: "类型代码" },
|
|
61
|
+
{ colKey: "name", title: "类型名称" },
|
|
62
|
+
{ colKey: "description", title: "描述" },
|
|
63
|
+
{ colKey: "sort", title: "排序" },
|
|
64
|
+
{ colKey: "operation", title: "操作" }
|
|
65
|
+
]),
|
|
66
|
+
endpoints: {
|
|
67
|
+
list: {
|
|
68
|
+
path: "/core/dictType/list",
|
|
69
|
+
dropValues: [0, ""],
|
|
70
|
+
dropKeyValue: {
|
|
71
|
+
keyword: [""]
|
|
72
|
+
},
|
|
73
|
+
buildData: () => {
|
|
74
|
+
return {
|
|
75
|
+
keyword: $Data.searchKeyword
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
delete: {
|
|
80
|
+
path: "/core/dictType/del",
|
|
81
|
+
idKey: "id",
|
|
82
|
+
confirm: (row) => {
|
|
83
|
+
return {
|
|
84
|
+
header: "确认删除",
|
|
85
|
+
body: `确认删除类型“${row.name}”吗?`,
|
|
86
|
+
confirmBtn: "删除",
|
|
87
|
+
status: "warning"
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
editVisible: false,
|
|
93
|
+
actionType: "add",
|
|
94
|
+
rowData: {}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
function onAdd(): void {
|
|
98
|
+
onAction("add", {});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function onDialogSuccess(reload: (options: { keepSelection?: boolean }) => void): void {
|
|
102
|
+
reload({ keepSelection: true });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function handleSearch(reload: (options: { keepSelection?: boolean; resetPage?: boolean }) => void): void {
|
|
106
|
+
reload({ keepSelection: false, resetPage: true });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function handleRefresh(reload: (options: { keepSelection?: boolean; resetPage?: boolean }) => void): void {
|
|
110
|
+
$Data.searchKeyword = "";
|
|
111
|
+
reload({ keepSelection: false, resetPage: true });
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function onAction(type: string, row: Record<string, unknown>): void {
|
|
115
|
+
if (type === "add") {
|
|
116
|
+
$Data.actionType = "add";
|
|
117
|
+
$Data.rowData = {};
|
|
118
|
+
$Data.editVisible = true;
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (type === "upd") {
|
|
123
|
+
$Data.actionType = "upd";
|
|
124
|
+
$Data.rowData = Object.assign({}, row);
|
|
125
|
+
$Data.editVisible = true;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function onDropdownAction(data: unknown, row: Record<string, unknown>, deleteRow: (r: Record<string, unknown>) => void): void {
|
|
130
|
+
const record = data as Record<string, unknown>;
|
|
131
|
+
const rawValue = record && record["value"] ? record["value"] : "";
|
|
132
|
+
const cmd = rawValue ? String(rawValue) : "";
|
|
133
|
+
if (cmd === "del") {
|
|
134
|
+
deleteRow(row);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
onAction(cmd, row);
|
|
138
|
+
}
|
|
139
|
+
</script>
|
|
140
|
+
|
|
141
|
+
<style scoped lang="scss">
|
|
142
|
+
.page-dict-type {
|
|
143
|
+
.main-tool .right {
|
|
144
|
+
display: flex;
|
|
145
|
+
gap: 8px;
|
|
146
|
+
align-items: center;
|
|
147
|
+
|
|
148
|
+
.t-input {
|
|
149
|
+
width: 240px;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
</style>
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
<template>
|
|
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" ref="formRef">
|
|
4
|
+
<TFormItem label="配置名称" prop="name">
|
|
5
|
+
<TInput v-model="$Data.formData.name" placeholder="请输入配置名称" :disabled="$Data.isSystem" />
|
|
6
|
+
</TFormItem>
|
|
7
|
+
<TFormItem label="配置代码" prop="code">
|
|
8
|
+
<TInput v-model="$Data.formData.code" placeholder="请输入配置代码,如:site_name" :disabled="$Prop.actionType === 'upd'" />
|
|
9
|
+
</TFormItem>
|
|
10
|
+
<TFormItem label="配置值" prop="value">
|
|
11
|
+
<TTextarea v-if="$Data.formData.valueType === 'json' || $Data.formData.valueType === 'text'" v-model="$Data.formData.value" placeholder="请输入配置值" :autosize="{ minRows: 3, maxRows: 8 }" />
|
|
12
|
+
<TInput v-else v-model="$Data.formData.value" placeholder="请输入配置值" />
|
|
13
|
+
</TFormItem>
|
|
14
|
+
<TFormItem label="值类型" prop="valueType">
|
|
15
|
+
<TSelect v-model="$Data.formData.valueType" :disabled="$Data.isSystem">
|
|
16
|
+
<TOption label="字符串" value="string" />
|
|
17
|
+
<TOption label="数字" value="number" />
|
|
18
|
+
<TOption label="布尔" value="boolean" />
|
|
19
|
+
<TOption label="JSON" value="json" />
|
|
20
|
+
</TSelect>
|
|
21
|
+
</TFormItem>
|
|
22
|
+
<TFormItem label="配置分组" prop="group">
|
|
23
|
+
<TSelect v-model="$Data.formData.group" placeholder="请选择分组" clearable :disabled="$Data.isSystem">
|
|
24
|
+
<TOption v-for="item in $Data2.groupOptions" :key="item" :label="item" :value="item" />
|
|
25
|
+
</TSelect>
|
|
26
|
+
</TFormItem>
|
|
27
|
+
<TFormItem label="排序" prop="sort">
|
|
28
|
+
<TInputNumber v-model="$Data.formData.sort" :min="0" :max="9999" :disabled="$Data.isSystem" />
|
|
29
|
+
</TFormItem>
|
|
30
|
+
<TFormItem label="描述说明" prop="description">
|
|
31
|
+
<TTextarea v-model="$Data.formData.description" placeholder="请输入描述说明" :autosize="{ minRows: 2, maxRows: 4 }" :disabled="$Data.isSystem" />
|
|
32
|
+
</TFormItem>
|
|
33
|
+
<TFormItem v-if="$Prop.actionType === 'upd' && !$Data.isSystem" label="状态" prop="state">
|
|
34
|
+
<TRadioGroup v-model="$Data.formData.state">
|
|
35
|
+
<TRadio :value="1">正常</TRadio>
|
|
36
|
+
<TRadio :value="2">禁用</TRadio>
|
|
37
|
+
</TRadioGroup>
|
|
38
|
+
</TFormItem>
|
|
39
|
+
</TForm>
|
|
40
|
+
</PageDialog>
|
|
41
|
+
</template>
|
|
42
|
+
|
|
43
|
+
<script setup lang="ts">
|
|
44
|
+
import { computed, reactive, ref } from "vue";
|
|
45
|
+
|
|
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
|
+
import PageDialog from "@/components/pageDialog.vue";
|
|
48
|
+
import { $Http } from "@/plugins/http";
|
|
49
|
+
|
|
50
|
+
const $Prop = defineProps({
|
|
51
|
+
modelValue: {
|
|
52
|
+
type: Boolean,
|
|
53
|
+
default: false
|
|
54
|
+
},
|
|
55
|
+
actionType: {
|
|
56
|
+
type: String,
|
|
57
|
+
default: "add"
|
|
58
|
+
},
|
|
59
|
+
rowData: {
|
|
60
|
+
type: Object,
|
|
61
|
+
default: () => ({})
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const $Emit = defineEmits<{
|
|
66
|
+
(e: "update:modelValue", value: boolean): void;
|
|
67
|
+
(e: "success"): void;
|
|
68
|
+
}>();
|
|
69
|
+
|
|
70
|
+
type PageDialogEventContext = {
|
|
71
|
+
close: () => void;
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// 表单引用
|
|
75
|
+
type TDesignFormInstance = {
|
|
76
|
+
validate: () => Promise<unknown>;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const formRef = ref<TDesignFormInstance | null>(null);
|
|
80
|
+
|
|
81
|
+
const dialogVisible = computed({
|
|
82
|
+
get: () => $Prop.modelValue,
|
|
83
|
+
set: (value) => {
|
|
84
|
+
$Emit("update:modelValue", value);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const $Data = reactive({
|
|
89
|
+
submitting: false,
|
|
90
|
+
isSystem: false,
|
|
91
|
+
formData: {
|
|
92
|
+
id: 0,
|
|
93
|
+
name: "",
|
|
94
|
+
code: "",
|
|
95
|
+
value: "",
|
|
96
|
+
valueType: "string",
|
|
97
|
+
group: "",
|
|
98
|
+
sort: 0,
|
|
99
|
+
description: "",
|
|
100
|
+
state: 1
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
const $Data2 = reactive({
|
|
105
|
+
formRules: {
|
|
106
|
+
name: [{ required: true, message: "请输入配置名称", trigger: "blur" }],
|
|
107
|
+
code: [
|
|
108
|
+
{ required: true, message: "请输入配置代码", trigger: "blur" },
|
|
109
|
+
{ pattern: /^[a-zA-Z0-9_]+$/, message: "配置代码只能包含字母、数字和下划线", trigger: "blur" }
|
|
110
|
+
],
|
|
111
|
+
value: [{ required: true, message: "请输入配置值", trigger: "blur" }],
|
|
112
|
+
valueType: [{ required: true, message: "请选择值类型", trigger: "change" }]
|
|
113
|
+
},
|
|
114
|
+
groupOptions: ["基础配置", "邮件配置", "存储配置", "安全配置", "其他"]
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
async function initData(): Promise<void> {
|
|
118
|
+
onShow();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function onShow(): void {
|
|
122
|
+
if ($Prop.actionType === "upd" && $Prop.rowData) {
|
|
123
|
+
const row = $Prop.rowData as Record<string, unknown>;
|
|
124
|
+
$Data.formData.id = (row["id"] as number) || 0;
|
|
125
|
+
$Data.formData.name = (row["name"] as string) || "";
|
|
126
|
+
$Data.formData.code = (row["code"] as string) || "";
|
|
127
|
+
$Data.formData.value = (row["value"] as string) || "";
|
|
128
|
+
$Data.formData.valueType = (row["valueType"] as string) || "string";
|
|
129
|
+
$Data.formData.group = (row["group"] as string) || "";
|
|
130
|
+
$Data.formData.sort = (row["sort"] as number) || 0;
|
|
131
|
+
$Data.formData.description = (row["description"] as string) || "";
|
|
132
|
+
$Data.formData.state = (row["state"] as number) || 1;
|
|
133
|
+
$Data.isSystem = row["isSystem"] === 1;
|
|
134
|
+
} else {
|
|
135
|
+
$Data.formData = {
|
|
136
|
+
id: 0,
|
|
137
|
+
name: "",
|
|
138
|
+
code: "",
|
|
139
|
+
value: "",
|
|
140
|
+
valueType: "string",
|
|
141
|
+
group: "",
|
|
142
|
+
sort: 0,
|
|
143
|
+
description: "",
|
|
144
|
+
state: 1
|
|
145
|
+
};
|
|
146
|
+
$Data.isSystem = false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function onSubmit(context?: PageDialogEventContext): Promise<void> {
|
|
151
|
+
const form = formRef.value;
|
|
152
|
+
if (!form) {
|
|
153
|
+
MessagePlugin.warning("表单未就绪");
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const valid = await form.validate();
|
|
158
|
+
if (valid !== true) return;
|
|
159
|
+
|
|
160
|
+
$Data.submitting = true;
|
|
161
|
+
try {
|
|
162
|
+
const api = $Prop.actionType === "upd" ? "/core/sysConfig/upd" : "/core/sysConfig/ins";
|
|
163
|
+
const res = await $Http.post(api, $Data.formData);
|
|
164
|
+
|
|
165
|
+
if (res.code === 0) {
|
|
166
|
+
MessagePlugin.success($Prop.actionType === "upd" ? "编辑成功" : "添加成功");
|
|
167
|
+
$Emit("success");
|
|
168
|
+
if (context && typeof context.close === "function") {
|
|
169
|
+
context.close();
|
|
170
|
+
}
|
|
171
|
+
} else {
|
|
172
|
+
MessagePlugin.error(res.msg || "操作失败");
|
|
173
|
+
}
|
|
174
|
+
} catch (_error) {
|
|
175
|
+
MessagePlugin.error("操作失败");
|
|
176
|
+
} finally {
|
|
177
|
+
$Data.submitting = false;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
initData();
|
|
182
|
+
</script>
|
|
183
|
+
|
|
184
|
+
<style scoped lang="scss"></style>
|