@befly-addon/admin 1.2.1 → 1.2.2
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/403_1/index.vue +75 -0
- package/adminViews/config/dict/components/edit.vue +109 -0
- package/adminViews/config/dict/index.vue +266 -0
- package/adminViews/config/dictType/components/edit.vue +100 -0
- package/adminViews/config/dictType/index.vue +244 -0
- package/adminViews/config/index.vue +12 -0
- package/adminViews/config/system/components/edit.vue +171 -0
- package/adminViews/config/system/index.vue +286 -0
- package/adminViews/index/components/addonList.vue +132 -0
- package/adminViews/index/components/environmentInfo.vue +100 -0
- package/adminViews/index/components/operationLogs.vue +112 -0
- package/adminViews/index/components/performanceMetrics.vue +145 -0
- package/adminViews/index/components/quickActions.vue +30 -0
- package/adminViews/index/components/serviceStatus.vue +192 -0
- package/adminViews/index/components/systemNotifications.vue +137 -0
- package/adminViews/index/components/systemOverview.vue +190 -0
- package/adminViews/index/components/systemResources.vue +111 -0
- package/adminViews/index/components/userInfo.vue +204 -0
- package/adminViews/index/index.vue +74 -0
- package/adminViews/log/email/index.vue +292 -0
- package/adminViews/log/index.vue +12 -0
- package/adminViews/log/login/index.vue +187 -0
- package/adminViews/log/operate/index.vue +249 -0
- package/adminViews/login_1/index.vue +415 -0
- package/adminViews/people/admin/components/edit.vue +168 -0
- package/adminViews/people/admin/index.vue +240 -0
- package/adminViews/people/index.vue +12 -0
- package/adminViews/permission/api/index.vue +149 -0
- package/adminViews/permission/index.vue +12 -0
- package/adminViews/permission/menu/index.vue +130 -0
- package/adminViews/permission/role/components/api.vue +361 -0
- package/adminViews/permission/role/components/edit.vue +142 -0
- package/adminViews/permission/role/components/menu.vue +118 -0
- package/adminViews/permission/role/index.vue +263 -0
- package/package.json +12 -10
- package/tsconfig.json +15 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="error-page">
|
|
3
|
+
<div class="error-content">
|
|
4
|
+
<div class="error-code">403</div>
|
|
5
|
+
<h1 class="error-title">无权限访问</h1>
|
|
6
|
+
<p class="error-description">抱歉,您没有访问该页面的权限</p>
|
|
7
|
+
<div class="error-actions">
|
|
8
|
+
<TButton theme="primary" @click="$Method.goHome">返回首页</TButton>
|
|
9
|
+
<TButton @click="$Method.goBack">返回上一页</TButton>
|
|
10
|
+
</div>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
</template>
|
|
14
|
+
|
|
15
|
+
<script setup>
|
|
16
|
+
import { useRouter } from "vue-router";
|
|
17
|
+
import { Button as TButton } from "tdesign-vue-next";
|
|
18
|
+
|
|
19
|
+
definePage({
|
|
20
|
+
meta: {
|
|
21
|
+
title: "403",
|
|
22
|
+
order: 101
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const router = useRouter();
|
|
27
|
+
|
|
28
|
+
const $Method = {
|
|
29
|
+
goHome() {
|
|
30
|
+
router.push("/");
|
|
31
|
+
},
|
|
32
|
+
goBack() {
|
|
33
|
+
router.back();
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
</script>
|
|
37
|
+
|
|
38
|
+
<style scoped lang="scss">
|
|
39
|
+
.error-page {
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
align-items: center;
|
|
43
|
+
justify-content: center;
|
|
44
|
+
min-height: 100vh;
|
|
45
|
+
background: var(--bg-color-page);
|
|
46
|
+
|
|
47
|
+
.error-code {
|
|
48
|
+
font-size: 120px;
|
|
49
|
+
font-weight: 700;
|
|
50
|
+
background: linear-gradient(135deg, var(--primary-color) 0%, #764ba2 100%);
|
|
51
|
+
-webkit-background-clip: text;
|
|
52
|
+
-webkit-text-fill-color: transparent;
|
|
53
|
+
background-clip: text;
|
|
54
|
+
margin: 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.error-message {
|
|
58
|
+
font-size: 24px;
|
|
59
|
+
color: var(--text-primary);
|
|
60
|
+
margin: 20px 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.error-description {
|
|
64
|
+
font-size: 16px;
|
|
65
|
+
color: var(--text-secondary);
|
|
66
|
+
margin: 8px 0 24px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.error-actions {
|
|
70
|
+
display: flex;
|
|
71
|
+
gap: 12px;
|
|
72
|
+
justify-content: center;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
</style>
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<TDialog v-model:visible="visible" :header="actionType === 'add' ? '添加字典项' : '编辑字典项'" width="600px" @confirm="$Method.handleSubmit" @close="$Method.handleClose">
|
|
3
|
+
<TForm ref="formRef" :data="$Data.formData" :rules="$Data.rules" label-width="100px">
|
|
4
|
+
<TFormItem label="字典类型" name="typeCode">
|
|
5
|
+
<TSelect v-model="$Data.formData.typeCode" placeholder="请选择字典类型" filterable>
|
|
6
|
+
<TOption v-for="item in typeList" :key="item.code" :value="item.code" :label="item.name" />
|
|
7
|
+
</TSelect>
|
|
8
|
+
</TFormItem>
|
|
9
|
+
<TFormItem label="键值" name="key">
|
|
10
|
+
<TInput v-model="$Data.formData.key" placeholder="请输入键名(英文/数字/下划线)" />
|
|
11
|
+
</TFormItem>
|
|
12
|
+
<TFormItem label="标签" name="label">
|
|
13
|
+
<TInput v-model="$Data.formData.label" placeholder="请输入标签(显示名称)" />
|
|
14
|
+
</TFormItem>
|
|
15
|
+
<TFormItem label="排序" name="sort">
|
|
16
|
+
<TInputNumber v-model="$Data.formData.sort" :min="0" placeholder="请输入排序值" />
|
|
17
|
+
</TFormItem>
|
|
18
|
+
<TFormItem label="备注" name="remark">
|
|
19
|
+
<TTextarea v-model="$Data.formData.remark" placeholder="请输入备注信息" :autosize="{ minRows: 3, maxRows: 6 }" />
|
|
20
|
+
</TFormItem>
|
|
21
|
+
</TForm>
|
|
22
|
+
</TDialog>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<script setup>
|
|
26
|
+
import { computed } from "vue";
|
|
27
|
+
|
|
28
|
+
import { Dialog as TDialog, 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
|
+
import { $Http } from "@/plugins/http";
|
|
30
|
+
|
|
31
|
+
const props = defineProps({
|
|
32
|
+
modelValue: Boolean,
|
|
33
|
+
actionType: String,
|
|
34
|
+
rowData: Object,
|
|
35
|
+
typeList: Array
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const emit = defineEmits(["update:modelValue", "success"]);
|
|
39
|
+
|
|
40
|
+
const visible = computed({
|
|
41
|
+
get: () => props.modelValue,
|
|
42
|
+
set: (val) => emit("update:modelValue", val)
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const formRef = $ref(null);
|
|
46
|
+
|
|
47
|
+
const $Data = $ref({
|
|
48
|
+
formData: {
|
|
49
|
+
typeCode: "",
|
|
50
|
+
key: "",
|
|
51
|
+
label: "",
|
|
52
|
+
sort: 0,
|
|
53
|
+
remark: ""
|
|
54
|
+
},
|
|
55
|
+
rules: {
|
|
56
|
+
typeCode: [{ required: true, message: "请选择字典类型" }],
|
|
57
|
+
key: [{ required: true, message: "请输入键值" }],
|
|
58
|
+
label: [{ required: true, message: "请输入标签" }]
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const $Method = {
|
|
63
|
+
async handleSubmit() {
|
|
64
|
+
try {
|
|
65
|
+
const valid = await formRef.validate();
|
|
66
|
+
const apiUrl = props.actionType === "add" ? "/addon/admin/dict/ins" : "/addon/admin/dict/upd";
|
|
67
|
+
const params = {
|
|
68
|
+
typeCode: $Data.formData.typeCode,
|
|
69
|
+
key: $Data.formData.key,
|
|
70
|
+
label: $Data.formData.label,
|
|
71
|
+
sort: $Data.formData.sort,
|
|
72
|
+
remark: $Data.formData.remark
|
|
73
|
+
};
|
|
74
|
+
if (props.actionType === "upd") {
|
|
75
|
+
params.id = props.rowData.id;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const res = await $Http(apiUrl, params);
|
|
79
|
+
if (res.code === 0) {
|
|
80
|
+
MessagePlugin.success(props.actionType === "add" ? "添加成功" : "更新成功");
|
|
81
|
+
visible.value = false;
|
|
82
|
+
emit("success");
|
|
83
|
+
} else {
|
|
84
|
+
MessagePlugin.error(res.msg || "操作失败");
|
|
85
|
+
}
|
|
86
|
+
} catch (error) {
|
|
87
|
+
MessagePlugin.error("操作失败");
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
handleClose() {
|
|
91
|
+
visible.value = false;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// 该组件由父组件 v-if 控制挂载/卸载,因此无需 watch:创建时初始化一次即可
|
|
96
|
+
if (props.actionType === "upd" && props.rowData) {
|
|
97
|
+
$Data.formData.typeCode = props.rowData.typeCode || "";
|
|
98
|
+
$Data.formData.key = props.rowData.key || "";
|
|
99
|
+
$Data.formData.label = props.rowData.label || "";
|
|
100
|
+
$Data.formData.sort = props.rowData.sort || 0;
|
|
101
|
+
$Data.formData.remark = props.rowData.remark || "";
|
|
102
|
+
} else {
|
|
103
|
+
$Data.formData.typeCode = "";
|
|
104
|
+
$Data.formData.key = "";
|
|
105
|
+
$Data.formData.label = "";
|
|
106
|
+
$Data.formData.sort = 0;
|
|
107
|
+
$Data.formData.remark = "";
|
|
108
|
+
}
|
|
109
|
+
</script>
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="page-dict page-table">
|
|
3
|
+
<div class="main-tool">
|
|
4
|
+
<div class="left">
|
|
5
|
+
<TButton theme="primary" @click="$Method.onAction('add', {})">
|
|
6
|
+
<template #icon>
|
|
7
|
+
<ILucidePlus />
|
|
8
|
+
</template>
|
|
9
|
+
</TButton>
|
|
10
|
+
</div>
|
|
11
|
+
<div class="right">
|
|
12
|
+
<TSelect v-model="$Data.searchTypeCode" placeholder="请选择字典类型" clearable filterable @change="$Method.handleSearch">
|
|
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="$Method.handleSearch" @clear="$Method.handleSearch">
|
|
16
|
+
<template #suffix-icon>
|
|
17
|
+
<ILucideSearch />
|
|
18
|
+
</template>
|
|
19
|
+
</TInput>
|
|
20
|
+
<TButton shape="circle" @click="$Method.handleRefresh">
|
|
21
|
+
<template #icon>
|
|
22
|
+
<ILucideRotateCw />
|
|
23
|
+
</template>
|
|
24
|
+
</TButton>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
<div class="main-content">
|
|
28
|
+
<div class="main-table">
|
|
29
|
+
<TTable
|
|
30
|
+
:data="$Data.tableData"
|
|
31
|
+
:columns="$Data.columns"
|
|
32
|
+
:loading="$Data.loading"
|
|
33
|
+
:active-row-keys="$Data.activeRowKeys"
|
|
34
|
+
row-key="id"
|
|
35
|
+
height="calc(100vh - var(--search-height) - var(--pagination-height) - var(--layout-gap) * 4)"
|
|
36
|
+
active-row-type="single"
|
|
37
|
+
@active-change="$Method.onActiveChange"
|
|
38
|
+
>
|
|
39
|
+
<template #operation="{ row }">
|
|
40
|
+
<TDropdown trigger="click" placement="bottom-right" @click="(data) => $Method.onAction(data.value, row)">
|
|
41
|
+
<TButton theme="primary" size="small">
|
|
42
|
+
操作
|
|
43
|
+
<template #suffix> <ILucideChevronDown /></template>
|
|
44
|
+
</TButton>
|
|
45
|
+
<TDropdownMenu slot="dropdown">
|
|
46
|
+
<TDropdownItem value="upd">
|
|
47
|
+
<ILucidePencil />
|
|
48
|
+
编辑
|
|
49
|
+
</TDropdownItem>
|
|
50
|
+
<TDropdownItem value="del" :divider="true">
|
|
51
|
+
<ILucideTrash2 style="width: 14px; height: 14px; margin-right: 6px" />
|
|
52
|
+
删除
|
|
53
|
+
</TDropdownItem>
|
|
54
|
+
</TDropdownMenu>
|
|
55
|
+
</TDropdown>
|
|
56
|
+
</template>
|
|
57
|
+
</TTable>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div class="main-detail">
|
|
61
|
+
<DetailPanel :data="$Data.currentRow" :fields="$Data.columns" />
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="main-page">
|
|
66
|
+
<TPagination :current-page="$Data.pagerConfig.currentPage" :page-size="$Data.pagerConfig.limit" :total="$Data.pagerConfig.total" @current-change="$Method.onPageChange" @page-size-change="$Method.handleSizeChange" />
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<EditDialog v-if="$Data.editVisible" v-model="$Data.editVisible" :action-type="$Data.actionType" :row-data="$Data.rowData" :type-list="$Data.typeList" @success="$Method.apiDictList" />
|
|
70
|
+
</div>
|
|
71
|
+
</template>
|
|
72
|
+
|
|
73
|
+
<script setup>
|
|
74
|
+
import { onMounted } from "vue";
|
|
75
|
+
|
|
76
|
+
import { Button as TButton, Table as TTable, Input as TInput, Select as TSelect, Option as TOption, Dropdown as TDropdown, DropdownMenu as TDropdownMenu, DropdownItem as TDropdownItem, Pagination as TPagination, MessagePlugin, DialogPlugin } from "tdesign-vue-next";
|
|
77
|
+
import ILucidePlus from "~icons/lucide/plus";
|
|
78
|
+
import ILucideRotateCw from "~icons/lucide/rotate-cw";
|
|
79
|
+
import ILucideSearch from "~icons/lucide/search";
|
|
80
|
+
import ILucidePencil from "~icons/lucide/pencil";
|
|
81
|
+
import ILucideTrash2 from "~icons/lucide/trash-2";
|
|
82
|
+
import ILucideChevronDown from "~icons/lucide/chevron-down";
|
|
83
|
+
import EditDialog from "./components/edit.vue";
|
|
84
|
+
import DetailPanel from "@/components/DetailPanel.vue";
|
|
85
|
+
import { $Http } from "@/plugins/http";
|
|
86
|
+
import { withDefaultColumns } from "befly-vite/utils/withDefaultColumns";
|
|
87
|
+
|
|
88
|
+
definePage({
|
|
89
|
+
meta: {
|
|
90
|
+
title: "字典列表",
|
|
91
|
+
order: 2
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const $Data = $ref({
|
|
96
|
+
tableData: [],
|
|
97
|
+
typeList: [],
|
|
98
|
+
loading: false,
|
|
99
|
+
activeRowKeys: [],
|
|
100
|
+
currentRow: null,
|
|
101
|
+
searchTypeCode: "",
|
|
102
|
+
searchKeyword: "",
|
|
103
|
+
columns: withDefaultColumns([
|
|
104
|
+
{ colKey: "id", title: "ID" },
|
|
105
|
+
{ colKey: "typeName", title: "类型名称" },
|
|
106
|
+
{ colKey: "typeCode", title: "类型代码" },
|
|
107
|
+
{ colKey: "label", title: "标签" },
|
|
108
|
+
{ colKey: "key", title: "键值" },
|
|
109
|
+
{ colKey: "sort", title: "排序", width: 100 },
|
|
110
|
+
{ colKey: "remark", title: "备注" },
|
|
111
|
+
{ colKey: "operation", title: "操作" }
|
|
112
|
+
]),
|
|
113
|
+
pagerConfig: {
|
|
114
|
+
currentPage: 1,
|
|
115
|
+
limit: 30,
|
|
116
|
+
total: 0,
|
|
117
|
+
align: "right",
|
|
118
|
+
layout: "total, prev, pager, next, jumper"
|
|
119
|
+
},
|
|
120
|
+
editVisible: false,
|
|
121
|
+
actionType: "add",
|
|
122
|
+
rowData: {}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const $Method = {
|
|
126
|
+
async initData() {
|
|
127
|
+
await $Method.apiDictTypeAll();
|
|
128
|
+
await $Method.apiDictList();
|
|
129
|
+
},
|
|
130
|
+
async apiDictTypeAll() {
|
|
131
|
+
try {
|
|
132
|
+
const res = await $Http("/addon/admin/dictType/all");
|
|
133
|
+
$Data.typeList = res.data.lists || [];
|
|
134
|
+
} catch (error) {
|
|
135
|
+
MessagePlugin.error("加载数据失败");
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
async apiDictList() {
|
|
139
|
+
$Data.loading = true;
|
|
140
|
+
try {
|
|
141
|
+
const res = await $Http("/addon/admin/dict/list", {
|
|
142
|
+
page: $Data.pagerConfig.currentPage,
|
|
143
|
+
limit: $Data.pagerConfig.limit,
|
|
144
|
+
typeCode: $Data.searchTypeCode,
|
|
145
|
+
keyword: $Data.searchKeyword
|
|
146
|
+
});
|
|
147
|
+
$Data.tableData = res.data.lists || [];
|
|
148
|
+
$Data.pagerConfig.total = res.data.total || 0;
|
|
149
|
+
|
|
150
|
+
if ($Data.tableData.length > 0) {
|
|
151
|
+
$Data.currentRow = $Data.tableData[0];
|
|
152
|
+
$Data.activeRowKeys = [$Data.tableData[0].id];
|
|
153
|
+
} else {
|
|
154
|
+
$Data.currentRow = null;
|
|
155
|
+
$Data.activeRowKeys = [];
|
|
156
|
+
}
|
|
157
|
+
} catch (error) {
|
|
158
|
+
MessagePlugin.error("加载数据失败");
|
|
159
|
+
} finally {
|
|
160
|
+
$Data.loading = false;
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
async apiDictDel(row) {
|
|
164
|
+
let dialog = null;
|
|
165
|
+
let destroyed = false;
|
|
166
|
+
|
|
167
|
+
const destroy = () => {
|
|
168
|
+
if (destroyed) return;
|
|
169
|
+
destroyed = true;
|
|
170
|
+
if (dialog && typeof dialog.destroy === "function") {
|
|
171
|
+
dialog.destroy();
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
dialog = DialogPlugin.confirm({
|
|
176
|
+
header: "确认删除",
|
|
177
|
+
body: `确认删除字典项“${row.label}”吗?`,
|
|
178
|
+
status: "warning",
|
|
179
|
+
confirmBtn: "删除",
|
|
180
|
+
cancelBtn: "取消",
|
|
181
|
+
onConfirm: async () => {
|
|
182
|
+
if (dialog && typeof dialog.setConfirmLoading === "function") {
|
|
183
|
+
dialog.setConfirmLoading(true);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
await $Http("/addon/admin/dict/del", { id: row.id });
|
|
188
|
+
MessagePlugin.success("删除成功");
|
|
189
|
+
destroy();
|
|
190
|
+
await $Method.apiDictList();
|
|
191
|
+
} catch (error) {
|
|
192
|
+
MessagePlugin.error("删除失败");
|
|
193
|
+
} finally {
|
|
194
|
+
if (dialog && typeof dialog.setConfirmLoading === "function") {
|
|
195
|
+
dialog.setConfirmLoading(false);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
onClose: () => {
|
|
200
|
+
destroy();
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
},
|
|
204
|
+
handleSearch() {
|
|
205
|
+
$Data.pagerConfig.currentPage = 1;
|
|
206
|
+
$Method.apiDictList();
|
|
207
|
+
},
|
|
208
|
+
handleRefresh() {
|
|
209
|
+
$Data.searchTypeCode = "";
|
|
210
|
+
$Data.searchKeyword = "";
|
|
211
|
+
$Data.pagerConfig.currentPage = 1;
|
|
212
|
+
$Method.apiDictList();
|
|
213
|
+
},
|
|
214
|
+
onPageChange({ currentPage }) {
|
|
215
|
+
$Data.pagerConfig.currentPage = currentPage;
|
|
216
|
+
$Method.apiDictList();
|
|
217
|
+
},
|
|
218
|
+
handleSizeChange({ pageSize }) {
|
|
219
|
+
$Data.pagerConfig.limit = pageSize;
|
|
220
|
+
$Data.pagerConfig.currentPage = 1;
|
|
221
|
+
$Method.apiDictList();
|
|
222
|
+
},
|
|
223
|
+
onActiveChange(value, context) {
|
|
224
|
+
if (value.length === 0 && $Data.activeRowKeys.length > 0) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
$Data.activeRowKeys = value;
|
|
228
|
+
$Data.currentRow = context.currentRowData;
|
|
229
|
+
},
|
|
230
|
+
onAction(type, row) {
|
|
231
|
+
if (type === "add") {
|
|
232
|
+
$Data.actionType = "add";
|
|
233
|
+
$Data.rowData = {};
|
|
234
|
+
$Data.editVisible = true;
|
|
235
|
+
} else if (type === "upd") {
|
|
236
|
+
$Data.actionType = "upd";
|
|
237
|
+
$Data.rowData = { ...row };
|
|
238
|
+
$Data.editVisible = true;
|
|
239
|
+
} else if (type === "del") {
|
|
240
|
+
$Method.apiDictDel(row);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
onMounted(() => {
|
|
246
|
+
$Method.initData();
|
|
247
|
+
});
|
|
248
|
+
</script>
|
|
249
|
+
|
|
250
|
+
<style scoped lang="scss">
|
|
251
|
+
.page-dict {
|
|
252
|
+
.main-tool .right {
|
|
253
|
+
display: flex;
|
|
254
|
+
gap: 8px;
|
|
255
|
+
align-items: center;
|
|
256
|
+
|
|
257
|
+
.t-select {
|
|
258
|
+
width: 200px;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.t-input {
|
|
262
|
+
width: 240px;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
</style>
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<TDialog v-model:visible="visible" :header="actionType === 'add' ? '添加字典类型' : '编辑字典类型'" width="600px" @confirm="$Method.handleSubmit" @close="$Method.handleClose">
|
|
3
|
+
<TForm ref="formRef" :data="$Data.formData" :rules="$Data.rules" label-width="100px">
|
|
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
|
+
</TDialog>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script setup>
|
|
21
|
+
import { computed } from "vue";
|
|
22
|
+
|
|
23
|
+
import { Dialog as TDialog, Form as TForm, FormItem as TFormItem, Input as TInput, Textarea as TTextarea, InputNumber as TInputNumber, MessagePlugin } from "tdesign-vue-next";
|
|
24
|
+
import { $Http } from "@/plugins/http";
|
|
25
|
+
|
|
26
|
+
const props = defineProps({
|
|
27
|
+
modelValue: Boolean,
|
|
28
|
+
actionType: String,
|
|
29
|
+
rowData: Object
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const emit = defineEmits(["update:modelValue", "success"]);
|
|
33
|
+
|
|
34
|
+
const visible = computed({
|
|
35
|
+
get: () => props.modelValue,
|
|
36
|
+
set: (val) => emit("update:modelValue", val)
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const formRef = $ref(null);
|
|
40
|
+
|
|
41
|
+
const $Data = $ref({
|
|
42
|
+
formData: {
|
|
43
|
+
code: "",
|
|
44
|
+
name: "",
|
|
45
|
+
description: "",
|
|
46
|
+
sort: 0
|
|
47
|
+
},
|
|
48
|
+
rules: {
|
|
49
|
+
code: [{ required: true, message: "请输入类型代码" }],
|
|
50
|
+
name: [{ required: true, message: "请输入类型名称" }]
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const $Method = {
|
|
55
|
+
async handleSubmit() {
|
|
56
|
+
const valid = await formRef.validate();
|
|
57
|
+
if (!valid) return;
|
|
58
|
+
|
|
59
|
+
try {
|
|
60
|
+
const apiUrl = props.actionType === "add" ? "/addon/admin/dictType/ins" : "/addon/admin/dictType/upd";
|
|
61
|
+
const params = {
|
|
62
|
+
code: $Data.formData.code,
|
|
63
|
+
name: $Data.formData.name,
|
|
64
|
+
description: $Data.formData.description,
|
|
65
|
+
sort: $Data.formData.sort
|
|
66
|
+
};
|
|
67
|
+
if (props.actionType === "upd") {
|
|
68
|
+
params.id = props.rowData.id;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const res = await $Http(apiUrl, params);
|
|
72
|
+
if (res.code === 0) {
|
|
73
|
+
MessagePlugin.success(props.actionType === "add" ? "添加成功" : "更新成功");
|
|
74
|
+
visible.value = false;
|
|
75
|
+
emit("success");
|
|
76
|
+
} else {
|
|
77
|
+
MessagePlugin.error(res.msg || "操作失败");
|
|
78
|
+
}
|
|
79
|
+
} catch (error) {
|
|
80
|
+
MessagePlugin.error("操作失败");
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
handleClose() {
|
|
84
|
+
visible.value = false;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// 该组件由父组件 v-if 控制挂载/卸载,因此无需 watch:创建时初始化一次即可
|
|
89
|
+
if (props.actionType === "upd" && props.rowData) {
|
|
90
|
+
$Data.formData.code = props.rowData.code || "";
|
|
91
|
+
$Data.formData.name = props.rowData.name || "";
|
|
92
|
+
$Data.formData.description = props.rowData.description || "";
|
|
93
|
+
$Data.formData.sort = props.rowData.sort || 0;
|
|
94
|
+
} else {
|
|
95
|
+
$Data.formData.code = "";
|
|
96
|
+
$Data.formData.name = "";
|
|
97
|
+
$Data.formData.description = "";
|
|
98
|
+
$Data.formData.sort = 0;
|
|
99
|
+
}
|
|
100
|
+
</script>
|