<template>
|
<!-- 左侧分类目录树,上部表格操作 card,下部 table 数据展示 -->
|
<div class="h100">
|
<el-row :gutter="8" class="h100">
|
<el-col :span="4" :xs="24" class="h100">
|
<el-card shadow="hover" class="h100" v-loading="treeLoading">
|
<!-- 目录树 -->
|
<LeftTreeByMgr
|
class="h100 left-tree-card"
|
ref="leftTreeRef"
|
:treedata="listTreeData"
|
title-name="分组列表"
|
:show-more-operate="true"
|
:show-add="true"
|
:folderIcon="() => false"
|
:current-node-key="currentListID"
|
:expand-on-click-node="false"
|
:default-expand-all="true"
|
:show-sorter="true"
|
@click="handleClickNode"
|
:customDropdown="true"
|
@tree-add="openOperateGroupDialog"
|
@node-drag-end="dragNodeEnd"
|
>
|
<template #customDropdown="{ data, node }">
|
<el-dropdown-menu>
|
<el-dropdown-item>
|
<el-button
|
@click.stop="() => openOperateGroupDialog(data)"
|
link
|
type="primary"
|
icon="ele-Edit"
|
style="cursor: pointer"
|
>
|
编辑
|
</el-button>
|
</el-dropdown-item>
|
<el-dropdown-item>
|
<el-button link type="danger" @click.stop="() => deleteCurrentGroup(data)" icon="ele-Delete" style="cursor: pointer">
|
删除
|
</el-button>
|
</el-dropdown-item>
|
<el-dropdown-item>
|
<el-button @click.stop="() => openParentDlg(data)" link type="primary" icon="ele-Menu" style="cursor: pointer">
|
父级
|
</el-button>
|
</el-dropdown-item>
|
</el-dropdown-menu>
|
</template>
|
</LeftTreeByMgr>
|
</el-card>
|
</el-col>
|
|
<el-col :span="20" :xs="24" class="flex-column h100">
|
<el-card shadow="hover" :body-style="{ paddingBottom: '0' }">
|
<!-- 查询、重置、排序、增加表单 -->
|
<el-form :inline="true" :model="parasQueryParams">
|
<el-form-item label="名称" prop="Name">
|
<el-input v-model="parasQueryParams.Name" style="width: 226.4px" placeholder="名称" clearable></el-input>
|
</el-form-item>
|
<el-form-item label="编码" prop="Code">
|
<el-input v-model="parasQueryParams.Code" style="width: 226.4px" placeholder="编码" clearable />
|
</el-form-item>
|
|
<el-form-item>
|
<el-button type="primary" icon="ele-Search" @click="handleQueryParasTable"> 查询 </el-button>
|
<el-button icon="ele-Refresh" @click="resetParasQuery">重置 </el-button>
|
<el-button icon="ele-Plus" @click="openOperateParasDialog()"> 增加 </el-button>
|
</el-form-item>
|
<el-form-item label="排序">
|
<el-switch
|
:disabled="displayParasTableData !== parasTableData"
|
v-model="isParasTableDrag"
|
@change="handleParasTableDrag"
|
inline-prompt
|
active-icon="ele-Check"
|
inactive-icon="ele-Close"
|
>
|
</el-switch>
|
</el-form-item>
|
</el-form>
|
</el-card>
|
|
<el-card class="flex-auto scroll-table-card" shadow="hover" style="margin-top: 8px">
|
<!-- 数据展示表格 -->
|
<el-table
|
v-loading="parasTableLoading"
|
ref="draggableTypeTableRef"
|
border
|
row-key="ID"
|
:row-class-name="isParasTableDrag ? 'cursor-move' : 'cursor-pointer'"
|
:cell-style="{ textAlign: 'center' }"
|
:header-cell-style="{ textAlign: 'center' }"
|
:data="displayParasTableData"
|
style="width: 100%"
|
highlight-current-row
|
>
|
<el-table-column prop="Name" width="240" label="名称" fixed="left" show-overflow-tooltip />
|
<el-table-column prop="Code" width="300" label="编码" show-overflow-tooltip />
|
<el-table-column prop="Format" label="格式" show-overflow-tooltip>
|
<template #default="scope">
|
{{ FORMAT_MAP[scope.row.Format] }}
|
</template>
|
</el-table-column>
|
<el-table-column prop="PValue" label="参数值" show-overflow-tooltip />
|
<el-table-column prop="Description" label="说明" width="550" show-overflow-tooltip />
|
<el-table-column label="操作" width="160" fixed="right" show-overflow-tooltip>
|
<template #default="scope">
|
<el-button icon="ele-Edit" size="small" text type="primary" @click="openOperateParasDialog(scope.row)">
|
编辑
|
</el-button>
|
<el-button icon="ele-Delete" size="small" text type="danger" @click="deleteCurrentTypeRow(scope.row)">
|
删除
|
</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</el-card>
|
</el-col>
|
</el-row>
|
<el-dialog
|
:destroy-on-close="true"
|
v-model="groupDialogIsShow"
|
width="400"
|
:close-on-click-modal="false"
|
@closed="closeGroupDialog"
|
>
|
<template #header>
|
<div style="color: #fff">
|
<SvgIcon :name="groupDialogHeaderIcon" :size="16" style="margin-right: 3px; display: inline; vertical-align: middle" />
|
<span> {{ groupDialogTitle }} </span>
|
</div>
|
</template>
|
|
<el-form :model="groupDialogFormValue" ref="groupDialogFormRef" :rules="groupDialogFormRules" label-width="55">
|
<el-form-item label="父级" v-if="!isEditGroupDialog" prop="ParentID">
|
<el-tree-select
|
default-expand-all
|
filterable
|
style="width: 100%"
|
v-model="groupDialogFormValue.ParentID"
|
:props="{
|
id: 'ID',
|
label: 'Name',
|
children: 'Children',
|
}"
|
:data="listTreeData"
|
node-key="ID"
|
:clearable="true"
|
:accordion="true"
|
:expandNode="false"
|
:check-strictly="true"
|
placeholder="请选择父级"
|
>
|
</el-tree-select>
|
</el-form-item>
|
<el-form-item label="名称" prop="Name">
|
<el-input placeholder="请输入名称" v-model="groupDialogFormValue.Name"></el-input>
|
</el-form-item>
|
|
<el-form-item label="说明" prop="Description">
|
<el-input placeholder="请输入说明" v-model="groupDialogFormValue.Description" type="textarea" :rows="3" />
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<div>
|
<el-button @click="closeGroupDialog">取 消</el-button>
|
<el-button type="primary" @click="submitGroupFormValue">确 定</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
|
<!-- 增加、修改数据对话框 -->
|
<el-dialog
|
:destroy-on-close="true"
|
v-model="parasDialogIsShow"
|
width="400"
|
:close-on-click-modal="false"
|
@closed="closeParasDialog"
|
>
|
<template #header>
|
<div style="color: #fff">
|
<SvgIcon :name="parasDialogHeaderIcon" :size="16" style="margin-right: 3px; display: inline; vertical-align: middle" />
|
<span> {{ parasDialogTitle }} </span>
|
</div>
|
</template>
|
|
<el-form :model="parasDialogFormValue" ref="parasDialogFormRef" :rules="parasDialogFormRules" label-width="78">
|
<el-form-item label="名称" prop="Name">
|
<el-input placeholder="请输入名称" v-model="parasDialogFormValue.Name"></el-input>
|
</el-form-item>
|
<el-form-item label="编码" prop="Code">
|
<el-input placeholder="请输入唯一编码" v-model="parasDialogFormValue.Code"></el-input>
|
</el-form-item>
|
<el-form-item label="格式" prop="Format">
|
<el-select v-model="parasDialogFormValue.Format" class="w100" filterable @change="parasFormatChange">
|
<el-option
|
v-for="item of Object.keys(FORMAT_MAP)"
|
:key="item"
|
:label="FORMAT_MAP[item]"
|
:value="parseInt(item)"
|
></el-option>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="参数值" prop="PValue">
|
<!-- 文本、多文本、数值、整数、长整数 -->
|
<el-input
|
v-if="INPUT_FORMAT.includes(parasDialogFormValue.Format)"
|
v-model="parasDialogFormValue.PValue"
|
v-bind="getInputProps(parasDialogFormValue.Format)"
|
></el-input>
|
<!-- 时间输入(包括有 choice) -->
|
<el-date-picker
|
class="w100"
|
v-else-if="parasDialogFormValue.Format === PropertyFormatEnum.Time"
|
value-format="YYYY-MM-DD"
|
v-model="parasDialogFormValue.PValue"
|
>
|
</el-date-picker>
|
<!-- 布尔值输入 -->
|
<el-radio-group
|
class="w100"
|
v-else-if="parasDialogFormValue.Format === PropertyFormatEnum.Boolean"
|
v-model="parasDialogFormValue.PValue"
|
>
|
<el-radio label="true" :value="true">是</el-radio>
|
<el-radio label="false" :value="false">否</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
<el-form-item label="说明" prop="Description">
|
<el-input placeholder="请输入说明" v-model="parasDialogFormValue.Description" type="textarea" :rows="3" />
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<div>
|
<el-button @click="closeParasDialog">取 消</el-button>
|
<el-button type="primary" @click="submitParasFormValue">确 定</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
<ParentDialog
|
v-model="parentDlgIsShow"
|
:data="listTreeData"
|
:api="parasGroupApi.UpdateBasicSysParasGroupTreeSortCode"
|
:rowData="parentDlgMapRow"
|
@submitSuccess="submitParentForm"
|
>
|
</ParentDialog>
|
</div>
|
</template>
|
|
<script setup lang="ts">
|
import type { PropType } from 'vue';
|
import { ref, computed, onMounted, nextTick } from 'vue';
|
import LeftTreeByMgr from '/@/components/tree/leftTreeByMgr.vue';
|
|
import * as parasApi from '/@/api/basic/sys/sysParas';
|
import * as parasGroupApi from '/@/api/basic/sys/sysParasGroup';
|
import { FORMAT_MAP, PropertyFormatEnum, INPUT_FORMAT } from '/@/projectCom/basic/types';
|
|
import type { FormInstance, FormRules } from 'element-plus';
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
import { useQueryTable } from '/@/hooks/useQueryTable';
|
import { updateSort, useTableSort } from '/@/hooks/useTableSort';
|
import { useValidateUniqueness } from '/@/hooks/useValidateUniqueness';
|
import { deepClone } from '/@/utils/other';
|
import { EXTEND_TYPE_MAP } from '/@/projectCom/basic/types';
|
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
|
import ParentDialog from '/@/components/dialog/parentDialog/ParentDialog.vue';
|
import { arrayIsEmpty, convertListToTree, flatten } from '/@/utils/util';
|
import { booleanRegex, dateRegex, integerRegex, numberRegex } from '/@/utils/toolsValidate';
|
|
const props = defineProps({
|
request: {
|
type: Function as PropType<(config: AxiosRequestConfig<any>) => Promise<AxiosResponse<any, any>>>,
|
},
|
});
|
//#region ====================== 左侧树数据,tree init ======================
|
const leftTreeRef = ref(null);
|
const treeLoading = ref(false);
|
const listTreeData = ref([]);
|
const currentListID = ref('');
|
const currentNode = ref(null);
|
const handleClickNode = (data) => {
|
nextTick(() => {
|
leftTreeRef.value?.treeRef.setCurrentKey(data.ID);
|
});
|
currentListID.value = data.ID;
|
currentNode.value = data;
|
getTypeTableData();
|
};
|
const getListTreeData = async (selectFirst = false) => {
|
treeLoading.value = true;
|
const res = await parasGroupApi.GetAllBasicSysParasGroup(props.request).finally(() => {
|
treeLoading.value = false;
|
});
|
if (res?.Code === 0) {
|
listTreeData.value = convertListToTree(res.Data) || [];
|
if (selectFirst) {
|
const firstListTreeNode = listTreeData.value[0];
|
if (firstListTreeNode) {
|
handleClickNode(firstListTreeNode);
|
} else {
|
parasTableData.value = [];
|
currentNode.value = null;
|
currentListID.value = null;
|
}
|
} else {
|
currentNode.value && handleClickNode(currentNode.value);
|
}
|
} else {
|
ElMessage.error('获取分组失败' + (res?.Message ? `,${JSON.stringify(res.Message)}` : ''));
|
}
|
};
|
//#endregion
|
//#region ====================== 获取、删除表格数据 ======================
|
const parasTableLoading = ref(false);
|
const parasTableData = ref([]);
|
const isParasTableDrag = ref(false);
|
const getTypeTableData = async () => {
|
parasTableLoading.value = true;
|
const res = await parasApi.GetBasicSysParasByGroupID({ GroupID: currentListID.value }, props.request).finally(() => {
|
parasTableLoading.value = false;
|
});
|
if (res?.Code === 0) {
|
parasTableData.value = res.Data || [];
|
} else {
|
ElMessage.error('获取系统参数失败' + (res?.Message ? `,${JSON.stringify(res.Message)}` : ''));
|
}
|
};
|
const deleteCurrentTypeRow = (row: any) => {
|
ElMessageBox.confirm(`确定删除系统参数:【${row.Name}】?`, '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning',
|
}).then(async () => {
|
const res = await parasApi.DeleteABasicSysParas(
|
{
|
ID: row.ID,
|
},
|
props.request
|
);
|
if (res?.Code === 0) {
|
if (res.Data) {
|
ElMessage.success('删除系统参数成功');
|
getTypeTableData();
|
} else {
|
ElMessage.error('删除系统参数失败');
|
}
|
} else {
|
ElMessage.error('删除系统参数失败' + (res?.Message ? `,${JSON.stringify(res.Message)}` : ''));
|
}
|
});
|
};
|
//#endregion
|
|
//#region ====================== 搜索表格,对表格排序 ======================
|
const parasQueryParams = ref({
|
Name: '',
|
Code: '',
|
});
|
const { handleDragStatus: handleParasTableDrag, draggableTableRef: draggableTypeTableRef } = useTableSort(
|
parasTableData,
|
parasApi.UpdateBasicSysParasSorter,
|
getTypeTableData,
|
undefined,
|
false,
|
props.request
|
);
|
|
const {
|
resetQuery: resetParasQuery,
|
handleQueryTable: handleQueryParasTable,
|
displayTableData: displayParasTableData,
|
} = useQueryTable(parasTableData, parasQueryParams, getTypeTableData);
|
//#endregion
|
|
//#region ====================== 增加、修改表格记录操作, dialog init======================
|
const isEditTypeDialog = ref(false);
|
const parasDialogTitle = computed(() => {
|
return isEditTypeDialog.value ? '修改系统参数' : '添加系统参数';
|
});
|
const parasDialogHeaderIcon = computed(() => {
|
return isEditTypeDialog.value ? 'ele-Edit' : 'ele-Plus';
|
});
|
const parasDialogFormValue = ref({
|
Name: '',
|
Code: '',
|
}) as any;
|
const parasDialogIsShow = ref(false);
|
const parasDialogFormRef = ref<FormInstance>(null);
|
const parasInitialCode = ref('');
|
const { uniquenessValidator: parasCodeValidator } = useValidateUniqueness(
|
parasApi.GetIsExistBasicSysParasCode,
|
parasInitialCode,
|
'编码',
|
'Code',
|
undefined,
|
false,
|
props.request
|
);
|
|
const pValueValidator = (rule, value, callback) => {
|
if (!value) {
|
callback('必填项!');
|
} else if (value && parasDialogFormValue.value.Format === PropertyFormatEnum.Numeric && !numberRegex.test(value)) {
|
callback('请输入数字!');
|
} else if (
|
value &&
|
[PropertyFormatEnum.Bigint, PropertyFormatEnum.Integer].includes(parasDialogFormValue.value.Format) &&
|
!integerRegex.test(value)
|
) {
|
callback('请输入整数!');
|
} else if (value && PropertyFormatEnum.Time === parasDialogFormValue.value.Format && !dateRegex.test(value)) {
|
callback('请输入正确的日期格式(yyyy-MM-dd HH:mm:ss 或 yyyy-MM-dd)');
|
} else if (value && PropertyFormatEnum.Boolean === parasDialogFormValue.value.Format && !booleanRegex.test(value)) {
|
callback('请输入 true 或 false');
|
} else {
|
callback();
|
}
|
};
|
|
const parasDialogFormRules = ref<FormRules>({
|
Name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
|
Code: [{ required: true, validator: parasCodeValidator as any, trigger: 'blur' }],
|
Format: [{ required: true, message: '请选择格式', trigger: 'change' }],
|
PValue: [{ required: true, validator: pValueValidator as any, trigger: 'blur' }],
|
});
|
const openOperateParasDialog = (row?) => {
|
if (!currentListID.value) {
|
return ElMessage.warning('请先选择分组!');
|
}
|
if (row) {
|
isEditTypeDialog.value = true;
|
const { ID, Name, Code, Description, Format, PValue } = row;
|
parasInitialCode.value = Code;
|
parasDialogFormValue.value = deepClone({ ID, Name, Code, Description, Format, PValue });
|
} else {
|
isEditTypeDialog.value = false;
|
parasInitialCode.value = '';
|
|
parasDialogFormValue.value = {
|
GroupID: currentListID.value,
|
Name: '',
|
Code: '',
|
Description: '',
|
Format: PropertyFormatEnum.Integer,
|
PValue: '',
|
};
|
}
|
parasDialogIsShow.value = true;
|
};
|
|
const closeParasDialog = () => {
|
parasDialogIsShow.value = false;
|
parasDialogFormRef.value.clearValidate();
|
};
|
|
const submitParasFormValue = async () => {
|
const valid = await parasDialogFormRef.value.validate().catch(() => {});
|
if (!valid) return;
|
|
if (isEditTypeDialog.value) {
|
const res = await parasApi.UpdateABasicSysParas(parasDialogFormValue.value, props.request);
|
if (res?.Code === 0) {
|
if (res.Data) {
|
getTypeTableData();
|
parasDialogIsShow.value = false;
|
ElMessage.success('修改系统参数成功');
|
} else {
|
ElMessage.error('修改系统参数失败');
|
}
|
} else {
|
ElMessage.error('修改系统参数失败' + (res?.Message ? `,${JSON.stringify(res.Message)}` : ''));
|
}
|
} else {
|
const res = await parasApi.InsertABasicSysParas(parasDialogFormValue.value, props.request);
|
if (res?.Code === 0) {
|
if (res.Data) {
|
getTypeTableData();
|
parasDialogIsShow.value = false;
|
ElMessage.success('添加系统参数成功');
|
} else {
|
ElMessage.error('添加系统参数失败');
|
}
|
} else {
|
ElMessage.error('添加系统参数失败' + (res?.Message ? `,${JSON.stringify(res.Message)}` : ''));
|
}
|
}
|
};
|
//#endregion
|
|
//#region ====================== 删除左侧树系统分组数据 ======================
|
|
const deleteCurrentGroup = (row: any) => {
|
ElMessageBox.confirm(`确定删除系统分组:【${row.Name}】?`, '提示', {
|
confirmButtonText: '确定',
|
cancelButtonText: '取消',
|
type: 'warning',
|
}).then(async () => {
|
const res = await parasGroupApi.DeleteABasicSysParasGroup(
|
{
|
ID: row.ID,
|
},
|
props.request
|
);
|
if (res?.Code === 0) {
|
if (res.Data) {
|
ElMessage.success('删除系统分组成功');
|
getListTreeData(true);
|
} else {
|
ElMessage.error('删除系统分组失败');
|
}
|
} else {
|
ElMessage.error('删除系统分组失败' + (res?.Message ? `,${JSON.stringify(res.Message)}` : ''));
|
}
|
});
|
};
|
//#endregion
|
|
//#region ====================== 增加、删除系统分组操作, dialog init======================
|
const isEditGroupDialog = ref(false);
|
const groupDialogTitle = computed(() => {
|
return isEditGroupDialog.value ? '修改系统分组' : '添加系统分组';
|
});
|
const groupDialogHeaderIcon = computed(() => {
|
return isEditGroupDialog.value ? 'ele-Edit' : 'ele-Plus';
|
});
|
const groupDialogFormValue = ref({
|
Name: '',
|
Code: '',
|
Description: '',
|
}) as any;
|
const groupDialogIsShow = ref(false);
|
const groupDialogFormRef = ref<FormInstance>(null);
|
|
const groupDialogFormRules = ref<FormRules>({
|
Name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
|
});
|
const openOperateGroupDialog = (data?) => {
|
if (data) {
|
isEditGroupDialog.value = true;
|
const { ID, Name, Code, Description } = data;
|
groupDialogFormValue.value = deepClone({ ID, Name, Code, Description });
|
} else {
|
isEditGroupDialog.value = false;
|
groupDialogFormValue.value = { Name: '', Code: '', Description: '' };
|
}
|
groupDialogIsShow.value = true;
|
};
|
|
const closeGroupDialog = () => {
|
groupDialogIsShow.value = false;
|
groupDialogFormRef.value.clearValidate();
|
};
|
|
const submitGroupFormValue = async () => {
|
const valid = await groupDialogFormRef.value.validate().catch(() => {});
|
if (!valid) return;
|
|
if (isEditGroupDialog.value) {
|
const res = await parasGroupApi.UpdateABasicSysParasGroup(groupDialogFormValue.value, props.request);
|
if (res?.Code === 0) {
|
if (res.Data) {
|
getListTreeData();
|
groupDialogIsShow.value = false;
|
ElMessage.success('修改系统分组成功');
|
} else {
|
ElMessage.error('修改系统分组失败');
|
}
|
} else {
|
ElMessage.error('修改系统分组失败' + (res?.Message ? `,${JSON.stringify(res.Message)}` : ''));
|
}
|
} else {
|
const res = await parasGroupApi.InsertABasicSysParasGroup(groupDialogFormValue.value, props.request);
|
if (res?.Code === 0) {
|
if (res.Data) {
|
getListTreeData(arrayIsEmpty(listTreeData.value));
|
groupDialogIsShow.value = false;
|
ElMessage.success('添加系统分组成功');
|
} else {
|
ElMessage.error('添加系统分组失败');
|
}
|
} else {
|
ElMessage.error('添加系统分组失败' + (res?.Message ? `,${JSON.stringify(res.Message)}` : ''));
|
}
|
}
|
};
|
//#endregion
|
|
//#region ====================== 左侧树拖拽 ======================
|
const dragNodeEnd = async (draggingNode, dropNode, dropType, ev, originTreeData) => {
|
updateSort(
|
listTreeData,
|
flatten(listTreeData.value),
|
originTreeData,
|
() => {
|
handleClickNode(draggingNode.data);
|
getListTreeData();
|
},
|
parasGroupApi.UpdateBasicSysParasGroupSorter,
|
() => {
|
handleClickNode(draggingNode.data);
|
},
|
undefined,
|
props.request
|
);
|
};
|
//#endregion
|
|
//#region ====================== 挂载时获取初始数据 ======================
|
onMounted(() => {
|
getListTreeData(true);
|
});
|
//#endregion
|
|
//#region ====================== 修改父级 ======================
|
const parentDlgIsShow = ref(false);
|
const parentDlgMapRow = ref(null);
|
const openParentDlg = (row?) => {
|
parentDlgMapRow.value = row;
|
parentDlgIsShow.value = true;
|
};
|
const submitParentForm = (res) => {
|
getListTreeData();
|
};
|
//#endregion
|
const getInputProps = (format: PropertyFormatEnum) => {
|
let inputProps = {};
|
switch (format) {
|
case PropertyFormatEnum.MultiText:
|
inputProps = {
|
type: 'textarea',
|
row: 3,
|
};
|
}
|
return {
|
...inputProps,
|
} as any;
|
};
|
|
const parasFormatChange = () => {
|
parasDialogFormValue.value.PValue = '';
|
};
|
</script>
|
<style scoped lang="scss"></style>
|