feat: 添加系统配置

This commit is contained in:
2025-02-12 22:36:29 +08:00
parent b1b00a3a02
commit 21d128ed66
7 changed files with 745 additions and 0 deletions

View File

@@ -102,6 +102,7 @@ menus:Abnormal: Abnormal Page
menus:FourZeroFour: "404" menus:FourZeroFour: "404"
menus:FourZeroOne: "403" menus:FourZeroOne: "403"
menus:Five: "500" menus:Five: "500"
menus:SystemConfig: System Config
status:Load: Loading... status:Load: Loading...
status:Message: Message status:Message: Message
status:Notify: Notify status:Notify: Notify

View File

@@ -102,6 +102,7 @@ menus:Abnormal: 异常页面
menus:FourZeroFour: "404" menus:FourZeroFour: "404"
menus:FourZeroOne: "403" menus:FourZeroOne: "403"
menus:Five: "500" menus:Five: "500"
menus:SystemConfig: 系统配置
status:Load: 加载中... status:Load: 加载中...
status:Message: 消息 status:Message: 消息
status:Notify: 通知 status:Notify: 通知

View File

@@ -1,5 +1,6 @@
import { http } from "@/utils/http"; import { http } from "@/utils/http";
import type { import type {
ConfigInfo,
DepartmentInfo, DepartmentInfo,
DepartmentRoleInfo, DepartmentRoleInfo,
PermissionInfo, PermissionInfo,
@@ -497,3 +498,99 @@ export const getUserGetDepartmentRolesAPI = (id: string) => {
`/api/department/roleList/${id}` `/api/department/roleList/${id}`
); );
}; };
// ---------------------------配置相关-------------------------------------
/**
* 添加配置参数
*/
interface AddConfigParams {
/**配置名称 */
name: string;
/**配置键值 */
key: string;
/**配置值 */
value: string;
/**系统配置 */
type: string;
/**备注 */
remark?: string;
}
/**
* 添加配置
* @param data
* @returns
*/
export const postAddConfigAPI = (data: AddConfigParams) => {
return http.request<null>("post", `/api/config/add`, {
data
});
};
/**
* 删除配置
*/
export const deleteConfigAPI = (id: string) => {
return http.request<null>("post", `/api/config/delete/${id}`);
};
/**
* 批量删除配置
* @param data 配置ID列表
*/
export const deleteConfigListAPI = (data: { ids: string[] }) => {
return http.request<null>("post", `/api/config/deleteList`, { data });
};
/**
* 更新配置
*/
export const putUpdateConfigAPI = (data: AddConfigParams, id: string) => {
return http.request<null>("post", `/api/config/update/${id}`, {
data
});
};
/**
* 获取配置信息
* @param id 配置ID
*/
export const getConfigAPI = (id: string) => {
return http.request<ConfigInfo>("get", `/api/config/info/${id}`);
};
/**
* 获取配置列表参数
*/
interface GetConfigListParams {
/**
* 页码
*/
page: number;
/**
* 每页数量
*/
pageSize: number;
/**
* 配置名称
*/
name?: string;
/**
* 配置键值
*/
key?: string;
/**
* 系统配置
*/
type?: string;
}
/**
* 获取配置列表
* @param params
*/
export const getConfigListAPI = (params: GetConfigListParams) => {
return http.request<QueryListResult<ConfigInfo>>("get", `/api/config/list`, {
params: filterEmptyObject(params)
});
};

View File

@@ -0,0 +1,108 @@
<template>
<el-form ref="ruleFormRef" :model="newFormInline" label-width="82px">
<el-row :gutter="30">
<re-col :value="24" :xm="24" :sm="24">
<el-form-item label="配置名称" prop="name">
<el-input
v-model="newFormInline.name"
clearable
placeholder="请输入配置名称"
/>
</el-form-item>
</re-col>
<re-col :value="24" :xm="24" :sm="24">
<el-form-item label="配置键名" prop="key">
<el-input
v-model="newFormInline.key"
clearable
placeholder="请输入配置键名~"
/>
</el-form-item>
</re-col>
<re-col :value="24" :xm="24" :sm="24">
<el-form-item label="配置键值" prop="value">
<el-input
v-model="newFormInline.value"
clearable
placeholder="请输入配置内容~"
/>
</el-form-item>
</re-col>
<re-col :value="24" :xm="24" :sm="24">
<el-form-item label="系统内置" prop="type">
<el-radio-group v-model="newFormInline.type">
<el-radio :value="true"> </el-radio>
<el-radio :value="false"> </el-radio>
</el-radio-group>
</el-form-item>
</re-col>
<re-col :value="24" :xm="24" :sm="24">
<el-form-item label="备注" prop="remark">
<el-input
v-model="newFormInline.remark"
type="textarea"
clearable
placeholder="请输入内容"
/>
</el-form-item>
</re-col>
</el-row>
</el-form>
</template>
<script setup lang="ts">
import { ref } from "vue";
import ReCol from "@/components/ReCol";
import { ConfigInfo } from "types/system";
interface FormItemProps {
/** 主键ID */
id: string;
/** 创建人 */
create_by: string;
/** 创建时间 */
create_time: string;
/** 更新人 */
update_by: string;
/** 更新时间 */
update_time: string;
/**配置名称 */
name: string;
/**配置键 */
key: string;
/**配置值 */
value: string;
/**系统配置 */
type: boolean;
/**备注 */
remark: string;
}
interface FormProps {
formInline: FormItemProps;
}
const props = withDefaults(defineProps<FormProps>(), {
formInline: () => ({
/** 主键ID */
id: "",
/** 创建人 */
create_by: "",
/** 创建时间 */
create_time: "",
/** 更新人 */
update_by: "",
/** 更新时间 */
update_time: "",
/**配置名称 */
name: "",
/**配置键 */
key: "",
/**配置值 */
value: "",
/**系统配置 */
type: true,
/**备注 */
remark: ""
})
});
const newFormInline = ref<ConfigInfo>(props.formInline);
defineExpose({ newFormInline });
</script>

View File

@@ -0,0 +1,193 @@
<template>
<div class="main">
<el-form
ref="formRef"
:inline="true"
:model="form"
class="search-form bg-bg_color w-[99/100] pl-8 pt-[12px]"
>
<el-form-item label="配置名称" prop="name">
<el-input
v-model="form.name"
placeholder="请输入配置名称"
clearable
class="!w-[180px]"
/>
</el-form-item>
<el-form-item label="配置键名" prop="key">
<el-input
v-model="form.key"
clearable
placeholder="请输入配置键名~"
class="!w-[180px]"
/>
</el-form-item>
<el-form-item label="系统内置" prop="type">
<el-select v-model="form.type" class="!w-[180px]">
<el-option label="是" :value="1" />
<el-option label="否" :value="0" />
</el-select>
</el-form-item>
<el-form-item>
<el-button
type="primary"
:icon="useRenderIcon('ri:search-line')"
:loading="loading"
@click="onSearch"
>
{{ t("buttons:Search") }}
</el-button>
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)">
{{ t("buttons:Reset") }}
</el-button>
</el-form-item>
</el-form>
<PureTableBar title="配置管理" :columns="columns" @refresh="onSearch">
<template #buttons>
<el-button
type="primary"
:icon="useRenderIcon(AddFill)"
@click="openDialog('新增')"
>
{{ t("buttons:Add") }}
</el-button>
</template>
<template v-slot="{ size, dynamicColumns }">
<div
v-if="selectedNum > 0"
v-motion-fade
class="bg-[var(--el-fill-color-light)] w-full h-[46px] mb-2 pl-4 flex items-center"
>
<div class="flex-auto">
<span
style="font-size: var(--el-font-size-base)"
class="text-[rgba(42,46,54,0.5)] dark:text-[rgba(220,220,242,0.5)]"
>
已选 {{ selectedNum }}
</span>
<el-button type="primary" text @click="onSelectionCancel">
{{ t("buttons:Deselect") }}
</el-button>
</div>
<el-popconfirm title="是否确认删除?" @confirm="onbatchDel">
<template #reference>
<el-button type="danger" text class="mr-1">
{{ t("buttons:DeleteInBatches") }}
</el-button>
</template>
</el-popconfirm>
</div>
<pure-table
ref="tableRef"
row-key="id"
adaptive
border
stripe
:adaptiveConfig="{ offsetBottom: 45 }"
align-whole="center"
table-layout="auto"
:loading="loading"
:size="size"
:data="dataList"
:columns="dynamicColumns"
:pagination="pagination"
:paginationSmall="size === 'small' ? true : false"
:header-cell-style="{
background: 'var(--el-fill-color-light)',
color: 'var(--el-text-color-primary)'
}"
@selection-change="handleSelectionChange"
@page-size-change="handleSizeChange"
@page-current-change="handleCurrentChange"
>
<template #operation="{ row }">
<el-button
class="reset-margin"
link
type="primary"
:size="size"
:icon="useRenderIcon(EditPen)"
@click="openDialog('修改', row)"
>
{{ t("buttons:Update") }}
</el-button>
<el-popconfirm
:title="`是否确认删除配置名为 ${row.name} 的这条数据`"
@confirm="handleDelete(row)"
>
<template #reference>
<el-button
class="reset-margin"
link
type="danger"
:size="size"
:icon="useRenderIcon(Delete)"
>
{{ t("buttons:Delete") }}
</el-button>
</template>
</el-popconfirm>
</template>
</pure-table>
</template>
</PureTableBar>
</div>
</template>
<script setup lang="ts">
defineOptions({
name: "ConfigIndex"
});
import { ref } from "vue";
import { useConfig } from "./utils/hook";
import { useI18n } from "vue-i18n";
import { PureTableBar } from "@/components/RePureTableBar";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import Delete from "@iconify-icons/ep/delete";
import EditPen from "@iconify-icons/ep/edit-pen";
import Refresh from "@iconify-icons/ep/refresh";
import AddFill from "@iconify-icons/ri/add-circle-line";
const { t } = useI18n();
/**
* 表格Ref
*/
const tableRef = ref();
const formRef = ref();
const {
form,
dataList,
loading,
pagination,
columns,
selectedNum,
onSearch,
openDialog,
resetForm,
handleDelete,
handleSizeChange,
handleCurrentChange,
handleSelectionChange,
onSelectionCancel,
onbatchDel
} = useConfig(tableRef);
</script>
<style scoped lang="scss">
:deep(.el-dropdown-menu__item i) {
margin: 0;
}
:deep(.el-button:focus-visible) {
outline: none;
}
.main-content {
margin: 24px 24px 0 !important;
}
.search-form {
:deep(.el-form-item) {
margin-bottom: 12px;
}
}
</style>

View File

@@ -0,0 +1,321 @@
import dayjs from "dayjs";
import editForm from "../components/form.vue";
import { message } from "@/utils/message";
import { type Ref, ref, reactive, onMounted, h, toRaw } from "vue";
import type { ConfigInfo } from "types/system";
import type { PaginationProps } from "@pureadmin/table";
import { addDialog } from "@/components/ReDialog";
import {
deleteConfigAPI,
deleteConfigListAPI,
getConfigListAPI,
postAddConfigAPI,
putUpdateConfigAPI
} from "@/api/system";
import { getKeyList } from "@pureadmin/utils";
export const useConfig = (tableRef: Ref) => {
/**
* 查询表单
*/
const form = reactive({
name: "",
key: "",
type: ""
});
/**
* 表单Ref
*/
const formRef = ref(null);
/**
* 数据列表
*/
const dataList = ref<ConfigInfo[]>([]);
/**
* 加载状态
*/
const loading = ref(true);
/**
* 已选数量
*/
const selectedNum = ref<number>(0);
/**
* 分页参数
*/
const pagination = reactive<PaginationProps>({
total: 0,
pageSize: 10,
currentPage: 1,
background: true
});
/**
* 表格列设置
*/
const columns: TableColumnList = [
{
label: "勾选列", // 如果需要表格多选此处label必须设置
type: "selection",
fixed: "left",
reserveSelection: true // 数据刷新后保留选项
},
{
label: "参数名称",
prop: "name"
},
{
label: "参数键名",
prop: "key"
},
{
label: "参数键值",
prop: "value"
},
{
label: "系统内置",
prop: "type",
formatter: ({ type }) => {
return type ? "是" : "否";
}
},
{
label: "创建时间",
prop: "create_time",
formatter: ({ create_time }) =>
dayjs(create_time).format("YYYY-MM-DD HH:mm:ss")
},
{
label: "操作",
fixed: "right",
width: 220,
slot: "operation"
}
];
/**
* 初次查询
*/
const onSearch = async () => {
loading.value = true;
const res = await getConfigListAPI({
page: pagination.currentPage,
pageSize: pagination.pageSize,
...toRaw(form)
});
if (res.success) {
dataList.value = res.data.result;
pagination.total = res.data.total;
pagination.currentPage = res.data.page;
pagination.pageSize = res.data.pageSize;
}
message(res.msg, {
type: res.success ? "success" : "error"
});
loading.value = false;
};
/**
* 重置表单
* @param formEl 表单ref
* @returns
*/
const resetForm = async (formEl: any) => {
if (!formEl) return;
formEl.resetFields();
await onSearch();
};
/**
* 处理删除
* @param row
*/
const handleDelete = async (row: ConfigInfo) => {
const res = await deleteConfigAPI(row.id);
if (res.success) {
onSearch();
}
message(res.msg, {
type: res.success ? "success" : "error"
});
};
/**
* 处理每页数量变化
*/
const handleSizeChange = async (val: number) => {
loading.value = true;
const res = await getConfigListAPI({
page: pagination.currentPage,
pageSize: val,
...toRaw(form)
});
if (res.success) {
dataList.value = res.data.result;
pagination.total = res.data.total;
pagination.currentPage = res.data.page;
pagination.pageSize = res.data.pageSize;
}
message(res.msg, {
type: res.success ? "success" : "error"
});
loading.value = false;
};
/**
* 处理页码变化
* @param val
*/
const handleCurrentChange = async (val: number) => {
loading.value = true;
const res = await getConfigListAPI({
page: val,
pageSize: pagination.pageSize,
...toRaw(form)
});
if (res.success) {
dataList.value = res.data.result;
pagination.total = res.data.total;
pagination.currentPage = res.data.page;
pagination.pageSize = res.data.pageSize;
}
message(res.msg, {
type: res.success ? "success" : "error"
});
loading.value = false;
};
/** 当CheckBox选择项发生变化时会触发该事件 */
const handleSelectionChange = async (val: any) => {
selectedNum.value = val.length;
// 重置表格高度
tableRef.value.setAdaptive();
};
/** 取消选择 */
const onSelectionCancel = async () => {
selectedNum.value = 0;
// 用于多选表格,清空用户的选择
tableRef.value.getTableRef().clearSelection();
};
/**
* 批量删除
*/
const onbatchDel = async () => {
// 返回当前选中的行
const curSelected = tableRef.value.getTableRef().getSelectionRows();
const res = await deleteConfigListAPI({
ids: getKeyList(curSelected, "id")
});
if (res.code === 200) {
message(`已删除项目名称为 ${getKeyList(curSelected, "name")} 的数据`, {
type: "success"
});
tableRef.value.getTableRef().clearSelection();
onSearch();
} else {
message(res.msg, { type: "error", duration: 5000 });
}
};
const openDialog = async (title = "新增", row?: ConfigInfo) => {
addDialog({
title: `${title}配置`,
props: {
formInline: {
/** 主键ID */
id: row?.id ?? "",
/** 创建人 */
create_by: row?.create_by ?? "",
/** 创建时间 */
create_time: row?.create_time ?? "",
/** 更新人 */
update_by: row?.update_by ?? "",
/** 更新时间 */
update_time: row?.update_time ?? "",
/**配置名称 */
name: row?.name ?? "",
/**配置键 */
key: row?.key ?? "",
/**配置值 */
value: row?.value ?? "",
/**系统配置 */
type: row?.type ?? true,
/**备注 */
remark: row?.remark ?? ""
}
},
width: "45%",
draggable: true,
fullscreenIcon: true,
closeOnClickModal: false,
contentRenderer: () =>
h(editForm, {
formInline: {
/** 主键ID */
id: row?.id ?? "",
/** 创建人 */
create_by: row?.create_by ?? "",
/** 创建时间 */
create_time: row?.create_time ?? "",
/** 更新人 */
update_by: row?.update_by ?? "",
/** 更新时间 */
update_time: row?.update_time ?? "",
/**配置名称 */
name: row?.name ?? "",
/**配置键 */
key: row?.key ?? "",
/**配置值 */
value: row?.value ?? "",
/**系统配置 */
type: row?.type ?? true,
/**备注 */
remark: row?.remark ?? ""
},
ref: formRef
}),
beforeSure: async (done, {}) => {
const FormData = formRef.value.newFormInline;
let form = {
key: FormData.key ?? "",
name: FormData.name ?? "",
value: FormData.value ?? "",
type: FormData.type ?? true,
remark: FormData.remark ?? ""
};
if (title === "新增") {
const res = await postAddConfigAPI(form);
if (res.success) {
done();
await onSearch();
}
message(res.msg, { type: res.success ? "success" : "error" });
} else {
const res = await putUpdateConfigAPI(form, row.id);
if (res.success) {
done();
await onSearch();
}
message(res.msg, { type: res.success ? "success" : "error" });
}
}
});
};
/**
* 页面加载执行
*/
onMounted(async () => {
await onSearch();
});
return {
form,
dataList,
loading,
pagination,
columns,
selectedNum,
openDialog,
onSearch,
resetForm,
handleDelete,
handleSizeChange,
handleCurrentChange,
handleSelectionChange,
onSelectionCancel,
onbatchDel
};
};

24
types/system.d.ts vendored
View File

@@ -222,3 +222,27 @@ export type DepartmentRoleInfo = {
/** 更新时间 */ /** 更新时间 */
update_time: string; update_time: string;
}; };
/**系统配置信息 */
export interface ConfigInfo {
/** 主键ID */
id: string;
/** 创建人 */
create_by: string;
/** 创建时间 */
create_time: string;
/** 更新人 */
update_by: string;
/** 更新时间 */
update_time: string;
/**配置名称 */
name: string;
/**配置键 */
key: string;
/**配置值 */
value: string;
/**系统配置 */
type: boolean;
/**备注 */
remark: string;
}