配置管理
This commit is contained in:
parent
c5aeb378d4
commit
2f7dd027c1
@ -10,13 +10,6 @@ export function getConfigList(params?) {
|
|||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
export function getConfigAllList(params?) {
|
|
||||||
return http.request({
|
|
||||||
url: '/config/list',
|
|
||||||
method: 'GET',
|
|
||||||
params,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* @description: 根据ID获取详情
|
* @description: 根据ID获取详情
|
||||||
*/
|
*/
|
||||||
@ -26,6 +19,15 @@ export function getConfigDetail(id) {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @description: 刷新缓存
|
||||||
|
*/
|
||||||
|
export function refreshCache() {
|
||||||
|
return http.request({
|
||||||
|
url: '/config/refreshCache',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @description: 添加配置
|
* @description: 添加配置
|
||||||
*/
|
*/
|
||||||
@ -65,3 +67,62 @@ export function configBatchDelete(data:any) {
|
|||||||
data
|
data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 配置项列表
|
||||||
|
*/
|
||||||
|
export function getConfigItemList(params?) {
|
||||||
|
return http.request({
|
||||||
|
url: '/config/item/page',
|
||||||
|
method: 'GET',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description: 根据ID获取详情
|
||||||
|
*/
|
||||||
|
export function getConfigItemDetail(id) {
|
||||||
|
return http.request({
|
||||||
|
url: '/config/item/detail/'+id,
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description: 添加配置项
|
||||||
|
*/
|
||||||
|
export function configItemAdd(data:any) {
|
||||||
|
return http.request({
|
||||||
|
url: '/config/item/add',
|
||||||
|
method: 'POST',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description: 更新配置项
|
||||||
|
*/
|
||||||
|
export function configItemUpdate(data:any) {
|
||||||
|
return http.request({
|
||||||
|
url: '/config/item/update',
|
||||||
|
method: 'PUT',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description: 删除配置项
|
||||||
|
*/
|
||||||
|
export function configItemDelete(id) {
|
||||||
|
return http.request({
|
||||||
|
url: '/config/item/delete/'+id,
|
||||||
|
method: 'DELETE',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @description: 批量删除配置项
|
||||||
|
*/
|
||||||
|
export function configItemBatchDelete(data:any) {
|
||||||
|
return http.request({
|
||||||
|
url: '/config/item/batchDelete',
|
||||||
|
method: 'DELETE',
|
||||||
|
data
|
||||||
|
});
|
||||||
|
}
|
@ -312,6 +312,7 @@
|
|||||||
size: unref(getTableSize),
|
size: unref(getTableSize),
|
||||||
stripe: unref(getStriped),
|
stripe: unref(getStriped),
|
||||||
'max-height': getDeviceHeight.value,
|
'max-height': getDeviceHeight.value,
|
||||||
|
height:getDeviceHeight.value,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
206
src/utils/validate.ts
Normal file
206
src/utils/validate.ts
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
/**
|
||||||
|
* 判断是否为空
|
||||||
|
* @param val 数据
|
||||||
|
*/
|
||||||
|
export const validateNull = (val: any) => {
|
||||||
|
if (typeof val === 'boolean') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (typeof val === 'number') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (val instanceof Array) {
|
||||||
|
if (val.length === 0) return true;
|
||||||
|
} else if (val instanceof Object) {
|
||||||
|
if (JSON.stringify(val) === '{}') return true;
|
||||||
|
} else {
|
||||||
|
if (val === 'null' || val == null || val === 'undefined' || val === undefined || val === '') return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const rule = {
|
||||||
|
/**
|
||||||
|
* 校验 请输入中文、英文、数字包括下划线
|
||||||
|
* 名称校验
|
||||||
|
*/
|
||||||
|
validatorNameCn(rule: any, value: any, callback: any) {
|
||||||
|
const acount = /^[\u4E00-\u9FA5A-Za-z0-9_]+$/;
|
||||||
|
if (value && !acount.test(value)) {
|
||||||
|
callback(new Error('请输入中文、英文、数字包括下划线'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 校验 请输入大写英文、下划线
|
||||||
|
* 名称校验
|
||||||
|
*/
|
||||||
|
validatorCapital(rule: any, value: any, callback: any) {
|
||||||
|
const acount = /^[A-Z_]+$/;
|
||||||
|
if (value && !acount.test(value)) {
|
||||||
|
callback(new Error('请输入大写英文、下划线'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验 请输入小写英文、下划线
|
||||||
|
* 名称校验
|
||||||
|
*/
|
||||||
|
validatorLowercase(rule: any, value: any, callback: any) {
|
||||||
|
const acount = /^[a-z_]+$/;
|
||||||
|
if (value && !acount.test(value)) {
|
||||||
|
callback(new Error('请输入小写英文、下划线'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验 请输入小写英文
|
||||||
|
* 名称校验
|
||||||
|
*/
|
||||||
|
validatorLower(rule: any, value: any, callback: any) {
|
||||||
|
const acount = /^[a-z]+$/;
|
||||||
|
if (value && !acount.test(value)) {
|
||||||
|
callback(new Error('请输入小写英文'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验首尾空白字符的正则表达式
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
checkSpace(rule: any, value: any, callback: any) {
|
||||||
|
const longrg = /[^\s]+$/;
|
||||||
|
if (!longrg.test(value)) {
|
||||||
|
callback(new Error('请输入非空格信息'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验手机号
|
||||||
|
*/
|
||||||
|
validatePhone(rule: any, value: any, callback: any) {
|
||||||
|
var isPhone = /^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$/;
|
||||||
|
|
||||||
|
if (value.indexOf('****') >= 0) {
|
||||||
|
return callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isPhone.test(value)) {
|
||||||
|
callback(new Error('请输入合法手机号'));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 数字 */
|
||||||
|
number(rule, value, callback) {
|
||||||
|
validateFn('number', rule, value, callback, '包含非数字字符');
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 字母 */
|
||||||
|
letter(rule, value, callback) {
|
||||||
|
validateFn('letter', rule, value, callback, '包含非字母字符');
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 字母和数字 */
|
||||||
|
letterAndNumber(rule, value, callback) {
|
||||||
|
validateFn('letterAndNumber', rule, value, callback, '只能输入字母或数字');
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 手机号码 */
|
||||||
|
mobilePhone(rule, value, callback) {
|
||||||
|
validateFn('mobilePhone', rule, value, callback, '手机号码格式有误');
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 字母开头,仅可包含数字 */
|
||||||
|
letterStartNumberIncluded(rule, value, callback) {
|
||||||
|
validateFn('letterStartNumberIncluded', rule, value, callback, '必须以字母开头,可包含数字');
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 禁止中文输入 */
|
||||||
|
noChinese(rule, value, callback) {
|
||||||
|
validateFn('noChinese', rule, value, callback, '不可输入中文字符');
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 必须中文输入 */
|
||||||
|
chinese(rule, value, callback) {
|
||||||
|
validateFn('chinese', rule, value, callback, '只能输入中文字符');
|
||||||
|
},
|
||||||
|
|
||||||
|
/* 电子邮箱 */
|
||||||
|
email(rule, value, callback) {
|
||||||
|
validateFn('email', rule, value, callback, '邮箱格式有误');
|
||||||
|
},
|
||||||
|
|
||||||
|
/* URL网址 */
|
||||||
|
url(rule, value, callback) {
|
||||||
|
validateFn('url', rule, value, callback, 'URL格式有误');
|
||||||
|
},
|
||||||
|
|
||||||
|
regExp(rule, value, callback) {
|
||||||
|
if (validateNull(value) || value.length <= 0) {
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pattern = new RegExp(rule.regExp);
|
||||||
|
|
||||||
|
if (!pattern.test(value)) {
|
||||||
|
const errTxt = rule.errorMsg || 'invalid value';
|
||||||
|
callback(new Error(errTxt));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @desc [自定义校验规则]
|
||||||
|
* @example
|
||||||
|
* import { validateRule } from "@/utils/validateRules";
|
||||||
|
* rules: [
|
||||||
|
* { validator: validateRule.emailValue, trigger: 'blur'}
|
||||||
|
* ]
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const getRegExp = function (validatorName) {
|
||||||
|
const commonRegExp = {
|
||||||
|
number: '^[-]?\\d+(\\.\\d+)?$',
|
||||||
|
letter: '^[A-Za-z]+$',
|
||||||
|
letterAndNumber: '^[A-Za-z0-9]+$',
|
||||||
|
mobilePhone: '^[1][3-9][0-9]{9}$',
|
||||||
|
letterStartNumberIncluded: '^[A-Za-z]+[A-Za-z\\d]*$',
|
||||||
|
noChinese: '^[^\u4e00-\u9fa5]+$',
|
||||||
|
chinese: '^[\u4e00-\u9fa5]+$',
|
||||||
|
email: '^([-_A-Za-z0-9.]+)@([_A-Za-z0-9]+\\.)+[A-Za-z0-9]{2,3}$',
|
||||||
|
url: '(https?|ftp|file)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]'
|
||||||
|
};
|
||||||
|
return commonRegExp[validatorName];
|
||||||
|
};
|
||||||
|
|
||||||
|
const validateFn = (validatorName, rule, value, callback, defaultErrorMsg) => {
|
||||||
|
if (validateNull(value) || value.length <= 0) {
|
||||||
|
callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reg = new RegExp(getRegExp(validatorName));
|
||||||
|
|
||||||
|
if (!reg.test(value)) {
|
||||||
|
const errTxt = rule.errorMsg || defaultErrorMsg;
|
||||||
|
callback(new Error(errTxt));
|
||||||
|
} else {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -12,13 +12,5 @@ export const columns = [
|
|||||||
{
|
{
|
||||||
label: '排序',
|
label: '排序',
|
||||||
prop: 'sort',
|
prop: 'sort',
|
||||||
},
|
}
|
||||||
{
|
|
||||||
label: '创建人',
|
|
||||||
prop: 'createUser',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '创建时间',
|
|
||||||
prop: 'createTime',
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
99
src/views/data/config/columnsItem.ts
Normal file
99
src/views/data/config/columnsItem.ts
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import { h } from 'vue';
|
||||||
|
import { ElTag } from 'element-plus';
|
||||||
|
export const columns = [
|
||||||
|
{
|
||||||
|
type: 'selection',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '配置项名称',
|
||||||
|
prop: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '配置项编码',
|
||||||
|
prop: 'code',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '配置项值',
|
||||||
|
prop: 'value',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '配置项类型',
|
||||||
|
prop: 'type',
|
||||||
|
render(record) {
|
||||||
|
let typeText = ''
|
||||||
|
switch (record.row.type) {
|
||||||
|
case 'hidden':
|
||||||
|
typeText='隐藏'
|
||||||
|
break;
|
||||||
|
case 'readonly':
|
||||||
|
typeText='只读文本'
|
||||||
|
break;
|
||||||
|
case 'number':
|
||||||
|
typeText='数字'
|
||||||
|
break;
|
||||||
|
case 'text':
|
||||||
|
typeText='单行文本'
|
||||||
|
break;
|
||||||
|
case 'textarea':
|
||||||
|
typeText='多行文本'
|
||||||
|
break;
|
||||||
|
case 'password':
|
||||||
|
typeText='密码'
|
||||||
|
break;
|
||||||
|
case 'radio':
|
||||||
|
typeText='单选框'
|
||||||
|
break;
|
||||||
|
case 'checkbox':
|
||||||
|
typeText='复选框'
|
||||||
|
break;
|
||||||
|
case 'select':
|
||||||
|
typeText='下拉框(单选)'
|
||||||
|
break;
|
||||||
|
case 'selects':
|
||||||
|
typeText='下拉框(多选)'
|
||||||
|
break;
|
||||||
|
case 'icon':
|
||||||
|
typeText='字体图标'
|
||||||
|
break;
|
||||||
|
case 'date':
|
||||||
|
typeText='日期'
|
||||||
|
break;
|
||||||
|
case 'datetime':
|
||||||
|
typeText='时间'
|
||||||
|
break;
|
||||||
|
case 'image':
|
||||||
|
typeText='单张图片'
|
||||||
|
break;
|
||||||
|
case 'images':
|
||||||
|
typeText='多张图片'
|
||||||
|
break;
|
||||||
|
case 'file':
|
||||||
|
typeText='单个文件'
|
||||||
|
case 'files':
|
||||||
|
typeText='多个文件'
|
||||||
|
break;
|
||||||
|
case 'ueditor':
|
||||||
|
typeText='富文本编辑器'
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return h('span', typeText || '-');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '配置项状态',
|
||||||
|
prop: 'status',
|
||||||
|
render(record) {
|
||||||
|
return h(
|
||||||
|
ElTag,
|
||||||
|
{
|
||||||
|
type: record.row.status ==1 ? 'success' : 'danger',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
default: () => (record.row.status ==1 ? '正常' : '停用'),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
127
src/views/data/config/configItem.vue
Normal file
127
src/views/data/config/configItem.vue
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<template>
|
||||||
|
<PageWrapper>
|
||||||
|
<BasicTable :columns="columns" :request="loadDataTable" :row-key="(row) => row.id" ref="tableRef"
|
||||||
|
:actionColumn="actionColumn" @selection-change="onSelectionChange">
|
||||||
|
<template #tableTitle>
|
||||||
|
<el-space>
|
||||||
|
<el-input type="text" v-model="params.name" placeholder="请输入配置项名称">
|
||||||
|
<template #prefix>
|
||||||
|
<el-icon class="el-input__icon">
|
||||||
|
<SearchOutlined />
|
||||||
|
</el-icon>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<el-button type="primary" @click="reloadTable"> 查询 </el-button>
|
||||||
|
<el-button type="primary" @click="handleAdd">新建</el-button>
|
||||||
|
<el-button type="danger" :disabled="!selectionData.length"@click="handleDelete()">删除</el-button>
|
||||||
|
</el-space>
|
||||||
|
</template>
|
||||||
|
</BasicTable>
|
||||||
|
<editDialog v-if="editVisible" :configId="configId" :configItemId="configItemId" v-model:visible="editVisible" @success="reloadTable">
|
||||||
|
</editDialog>
|
||||||
|
</PageWrapper>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { ref, reactive, h, nextTick, watch, defineAsyncComponent } from 'vue';
|
||||||
|
import { SearchOutlined } from '@vicons/antd';
|
||||||
|
import { TableAction } from '@/components/Table';
|
||||||
|
import { getConfigItemList, configItemDelete, configItemBatchDelete } from '@/api/data/config';
|
||||||
|
import { columns } from './columnsItem';
|
||||||
|
import { message, confirm } from "@/utils/auth";
|
||||||
|
const editDialog = defineAsyncComponent(() =>
|
||||||
|
import('./editItem.vue')
|
||||||
|
)
|
||||||
|
const tableRef = ref();
|
||||||
|
const editVisible = ref(false)
|
||||||
|
const selectionData = ref([])
|
||||||
|
const configItemId = ref(0)
|
||||||
|
const params = ref({
|
||||||
|
name: '',
|
||||||
|
});
|
||||||
|
const props = defineProps({
|
||||||
|
configId: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
watch(
|
||||||
|
() => props.configId,
|
||||||
|
async (value) => {
|
||||||
|
if(value){
|
||||||
|
await nextTick()
|
||||||
|
reloadTable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const actionColumn = reactive({
|
||||||
|
lable: 150,
|
||||||
|
title: '操作',
|
||||||
|
prop: 'action',
|
||||||
|
fixed: 'right',
|
||||||
|
render(record) {
|
||||||
|
return h(TableAction as any, {
|
||||||
|
style: 'text',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
label: '编辑',
|
||||||
|
type: 'warning',
|
||||||
|
onClick: handleEdit.bind(null, record),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '删除',
|
||||||
|
type: 'danger',
|
||||||
|
onClick: handleDelete.bind(null, record),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//刷新字典项值列表
|
||||||
|
function reloadTable() {
|
||||||
|
tableRef.value.reload({ pageNo: 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
//加载字典项值列表
|
||||||
|
const loadDataTable = async (res) => {
|
||||||
|
const result = await getConfigItemList({ ...params.value, configId:props.configId, ...res });
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
//新建字典
|
||||||
|
const handleAdd = async () => {
|
||||||
|
configItemId.value=0
|
||||||
|
await nextTick();
|
||||||
|
editVisible.value=true
|
||||||
|
};
|
||||||
|
//编辑字典
|
||||||
|
const handleEdit = async (record: Recordable) => {
|
||||||
|
configItemId.value=record.row.id
|
||||||
|
await nextTick();
|
||||||
|
editVisible.value=true
|
||||||
|
};
|
||||||
|
//删除字典项
|
||||||
|
async function handleDelete(record: Recordable) {
|
||||||
|
let ids = []
|
||||||
|
if (!record) {
|
||||||
|
ids = selectionData.value.map(({ id }) => id);
|
||||||
|
}
|
||||||
|
await confirm('确定要删除?');
|
||||||
|
record ? await configItemDelete(record.row.id) : await configItemBatchDelete(ids);
|
||||||
|
message("删除成功");
|
||||||
|
reloadTable()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onSelectionChange(value) {
|
||||||
|
selectionData.value = value
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
233
src/views/data/config/editItem.vue
Normal file
233
src/views/data/config/editItem.vue
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog
|
||||||
|
v-model="props.visible"
|
||||||
|
:title="props.configItemId?'编辑配置项':'新增配置项'"
|
||||||
|
width="500"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:before-close="dialogClose"
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
class="ls-form"
|
||||||
|
ref="formRef"
|
||||||
|
:model="formData"
|
||||||
|
label-width="100px"
|
||||||
|
>
|
||||||
|
<el-form-item
|
||||||
|
label="配置项名称"
|
||||||
|
prop="name"
|
||||||
|
:rules="{ required: true, message: '请输入配置项名称', trigger: 'blur' }"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
class="ls-input"
|
||||||
|
v-model="formData.name"
|
||||||
|
placeholder="请输入配置项名称"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="配置项编码"
|
||||||
|
prop="code"
|
||||||
|
:rules="{ required: true, message: '请输入配置项编码', trigger: 'blur' }"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
class="ls-input"
|
||||||
|
v-model="formData.code"
|
||||||
|
placeholder="请输入配置项编码"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="配置项值"
|
||||||
|
prop="value"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
class="ls-input"
|
||||||
|
v-model="formData.value"
|
||||||
|
placeholder="请输入配置项值"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="配置项类型" prop="type" class="flex-1" :rules="{ required: true, message: '请选择配置项类型', trigger: 'change' }">
|
||||||
|
<el-select v-model="formData.type" class="flex-1" clearable placeholder="请选择配置项类型">
|
||||||
|
<el-option v-for="(item, index) in typeList" :key="index" :label="item.name" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
label="配置项源"
|
||||||
|
prop="options"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
class="ls-input"
|
||||||
|
v-model="formData.options"
|
||||||
|
placeholder="请输入配置项数据源"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="排序" prop="sort">
|
||||||
|
<el-input-number v-model="formData.sort"/>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="配置项状态" prop="status">
|
||||||
|
<el-radio-group v-model="formData.status" name="status">
|
||||||
|
<el-radio :value="1">正常</el-radio>
|
||||||
|
<el-radio :value="2">停用</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="备注" prop="note">
|
||||||
|
<el-input v-model="formData.note" type="textarea" placeholder="请输入备注" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<span class="dialog-footer">
|
||||||
|
<el-button @click="dialogClose">取消</el-button>
|
||||||
|
<el-button :loading="subLoading" type="primary" @click="submit">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import type {FormInstance} from "element-plus";
|
||||||
|
import {getConfigItemDetail,configItemAdd,configItemUpdate} from "@/api/data/config";
|
||||||
|
import {onMounted, ref,reactive, shallowRef} from "vue";
|
||||||
|
import {message} from "@/utils/auth";
|
||||||
|
import {useLockFn} from "@/utils/useLockFn";
|
||||||
|
|
||||||
|
const emit = defineEmits(["success", "update:visible"]);
|
||||||
|
const formRef = shallowRef<FormInstance>();
|
||||||
|
const formData = reactive({
|
||||||
|
id: "",
|
||||||
|
name: "",
|
||||||
|
code:"",
|
||||||
|
value: "",
|
||||||
|
sort: 0,
|
||||||
|
options:'',
|
||||||
|
type:'',
|
||||||
|
status:1,
|
||||||
|
note:''
|
||||||
|
});
|
||||||
|
const typeList = ref([
|
||||||
|
{
|
||||||
|
name:'隐藏',
|
||||||
|
value:'hidden'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'只读文本',
|
||||||
|
value:'readonly'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'数字',
|
||||||
|
value:'number'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'单行文本',
|
||||||
|
value:'text'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'多行文本',
|
||||||
|
value:'textarea'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'密码',
|
||||||
|
value:'password'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'单选框',
|
||||||
|
value:'radio'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'复选框',
|
||||||
|
value:'checkbox'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'下拉框(单选)',
|
||||||
|
value:'select'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'下拉框(多选)',
|
||||||
|
value:'selects'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'字体图标',
|
||||||
|
value:'icon'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'日期',
|
||||||
|
value:'date'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'时间',
|
||||||
|
value:'datetime'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'单张图片',
|
||||||
|
value:'image'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'多张图片',
|
||||||
|
value:'images'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'单个文件',
|
||||||
|
value:'file'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'多个文件',
|
||||||
|
value:'files'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name:'富文本编辑器',
|
||||||
|
value:'ueditor'
|
||||||
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
configId: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
configItemId: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleSubmit = async () => {
|
||||||
|
await formRef.value?.validate();
|
||||||
|
props.configItemId ? await configItemUpdate({...formData,configId:props.configId}) : await configItemAdd({...formData,configId:props.configId});
|
||||||
|
message("操作成功");
|
||||||
|
emit("update:visible", false);
|
||||||
|
emit("success");
|
||||||
|
};
|
||||||
|
|
||||||
|
const dialogClose = () => {
|
||||||
|
emit("update:visible", false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const { isLock:subLoading,lockFn: submit } = useLockFn(handleSubmit);
|
||||||
|
|
||||||
|
|
||||||
|
const setFormData = async () => {
|
||||||
|
const data = await getConfigItemDetail(props.configItemId);
|
||||||
|
for (const key in formData) {
|
||||||
|
if (data[key] != null && data[key] != undefined) {
|
||||||
|
//@ts-ignore
|
||||||
|
formData[key] = data[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (props.configItemId) {
|
||||||
|
setFormData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
@ -1,144 +1,124 @@
|
|||||||
<template>
|
<template>
|
||||||
<PageWrapper>
|
<PageWrapper>
|
||||||
<el-card :bordered="false" class="pt-3 mb-3 proCard">
|
<el-row :gutter="10" class="mt-3">
|
||||||
<BasicForm @register="register" @submit="handleSubmit" @reset="handleReset"></BasicForm>
|
<el-col :xs="24" :sm="24" :md="8" :lg="8" :xl="8" class="mb-4">
|
||||||
</el-card>
|
<el-card shadow="hover" class="border-0">
|
||||||
<el-card :bordered="false" class="proCard">
|
<template #header>
|
||||||
<BasicTable
|
<el-row>
|
||||||
:columns="columns"
|
<el-col :span="20">
|
||||||
:request="loadDataTable"
|
<el-input type="text" v-model="params.name" clearable placeholder="请输入配置名称">
|
||||||
:row-key="(row) => row.id"
|
<template #prefix>
|
||||||
ref="tableRef"
|
|
||||||
:actionColumn="actionColumn"
|
|
||||||
@selection-change="onSelectionChange"
|
|
||||||
>
|
|
||||||
<template #tableTitle>
|
|
||||||
<el-button type="primary" @click="handleAdd">
|
|
||||||
<template #icon>
|
|
||||||
<el-icon class="el-input__icon">
|
<el-icon class="el-input__icon">
|
||||||
<PlusOutlined />
|
<SearchOutlined />
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</template>
|
</template>
|
||||||
添加配置
|
</el-input>
|
||||||
</el-button>
|
</el-col>
|
||||||
<el-button type="danger" @click="handleDelete()" :disabled="!selectionData.length">
|
<el-col :span="4" style="text-align: right;">
|
||||||
<template #icon>
|
<el-button type="primary" @click="reloadTable"> 查询 </el-button>
|
||||||
<el-icon class="el-input__icon">
|
</el-col>
|
||||||
<Delete />
|
</el-row>
|
||||||
</el-icon>
|
<div style="margin-top:15px;">
|
||||||
|
<el-button type="primary" @click="addConfig">新建</el-button>
|
||||||
|
<el-button type="danger" :disabled="!selectionData.length" @click="handleDelete()">删除</el-button>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
删除
|
<BasicTable :columns="columns" :showTableSetting="false" :request="loadDataTable" :row-key="(row) => row.id"
|
||||||
</el-button>
|
ref="tableRef" :actionColumn="actionColumn" @selection-change="onSelectionChange" highlight-current-row
|
||||||
</template>
|
@row-click="onCheckedRow" />
|
||||||
</BasicTable>
|
|
||||||
</el-card>
|
</el-card>
|
||||||
|
</el-col>
|
||||||
<editDialog
|
<el-col :xs="24" :sm="24" :md="16" :lg="16" :xl="16" class="mb-4">
|
||||||
v-if="editVisible"
|
<el-card shadow="hover" class="mb-4 border-0 proCard">
|
||||||
:configId="configId"
|
<configItem :configId="configId" v-if="configItemShow"></configItem>
|
||||||
v-model:visible="editVisible"
|
</el-card>
|
||||||
@success="reloadTable"
|
</el-col>
|
||||||
>
|
</el-row>
|
||||||
|
<editDialog v-if="editVisible" :configId="configId" v-model:visible="editVisible" @success="reloadTable">
|
||||||
</editDialog>
|
</editDialog>
|
||||||
</PageWrapper>
|
</PageWrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { reactive, ref, h,nextTick,defineAsyncComponent } from 'vue';
|
import { ref, reactive, h, nextTick, defineAsyncComponent } from 'vue';
|
||||||
import { ColProps } from 'element-plus';
|
import { SearchOutlined } from '@vicons/antd';
|
||||||
import { schemas } from './querySchemas';
|
|
||||||
import { useForm } from '@/components/Form/index';
|
|
||||||
import { TableAction } from '@/components/Table';
|
import { TableAction } from '@/components/Table';
|
||||||
import { getConfigList, configDelete, configBatchDelete } from '@/api/data/config';
|
import { getConfigList, configDelete, configBatchDelete } from '@/api/data/config';
|
||||||
import { columns } from './columns';
|
import { columns } from './columns';
|
||||||
import { PlusOutlined } from '@vicons/antd';
|
import configItem from './configItem.vue';
|
||||||
import { message, confirm } from "@/utils/auth";
|
import { message, confirm } from "@/utils/auth";
|
||||||
const editDialog = defineAsyncComponent(() =>
|
const editDialog = defineAsyncComponent(() =>
|
||||||
import('./edit.vue')
|
import('./edit.vue')
|
||||||
)
|
)
|
||||||
const configId = ref(0)
|
const configId = ref(0)
|
||||||
|
const configItemShow = ref(false)
|
||||||
|
const tableRef = ref();
|
||||||
const editVisible = ref(false)
|
const editVisible = ref(false)
|
||||||
const selectionData = ref([])
|
const selectionData = ref([])
|
||||||
const tableRef = ref();
|
const params = ref({
|
||||||
const formParams = reactive({
|
|
||||||
name: '',
|
name: '',
|
||||||
status:'',
|
|
||||||
type:''
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const actionColumn = reactive({
|
const actionColumn = reactive({
|
||||||
width: 250,
|
lable: 150,
|
||||||
label: '操作',
|
title: '操作',
|
||||||
prop: 'action',
|
prop: 'action',
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
render(record) {
|
render(record) {
|
||||||
return h(TableAction, {
|
return h(TableAction as any, {
|
||||||
style: 'button',
|
style: 'text',
|
||||||
actions: [
|
actions: [
|
||||||
{
|
{
|
||||||
label: '编辑',
|
label: '编辑',
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
onClick: handleEdit.bind(null, record),
|
onClick: handleEdit.bind(null, record),
|
||||||
ifShow: () => {
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
// auth: ['basic_list'],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '删除',
|
label: '删除',
|
||||||
type: 'danger',
|
type: 'danger',
|
||||||
onClick: handleDelete.bind(null, record),
|
onClick: handleDelete.bind(null, record),
|
||||||
// 根据业务控制是否显示 isShow 和 auth 是并且关系
|
}
|
||||||
ifShow: () => {
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
// 根据权限控制是否显示: 有权限,会显示,支持多个
|
|
||||||
// auth: ['basic_list'],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const loadDataTable = async (res: any) => {
|
|
||||||
const result = await getConfigList({ ...formParams, ...res });
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
function reloadTable() {
|
//新建字典
|
||||||
tableRef.value.reload({pageNo:1});
|
const addConfig = async () => {
|
||||||
}
|
|
||||||
const [register, {}] = useForm({
|
|
||||||
labelWidth: 80,
|
|
||||||
layout: 'horizontal',
|
|
||||||
colProps: { span: 6 } as ColProps,
|
|
||||||
submitOnReset:true,
|
|
||||||
schemas
|
|
||||||
});
|
|
||||||
function handleSubmit(values: Recordable) {
|
|
||||||
handleReset()
|
|
||||||
for (const key in values) {
|
|
||||||
formParams[key] = values[key]
|
|
||||||
}
|
|
||||||
reloadTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleReset() {
|
|
||||||
for (const key in formParams) {
|
|
||||||
formParams[key] ='';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const handleAdd = async () => {
|
|
||||||
configId.value=0
|
configId.value=0
|
||||||
await nextTick();
|
await nextTick();
|
||||||
editVisible.value=true
|
editVisible.value=true
|
||||||
};
|
};
|
||||||
|
//编辑字典
|
||||||
const handleEdit = async (record: Recordable) => {
|
const handleEdit = async (record: Recordable) => {
|
||||||
configId.value=record.row.id
|
configId.value=record.row.id
|
||||||
await nextTick();
|
await nextTick();
|
||||||
editVisible.value=true
|
editVisible.value=true
|
||||||
};
|
};
|
||||||
|
//选择字典项
|
||||||
|
function onCheckedRow(row) {
|
||||||
|
configId.value = row.id
|
||||||
|
}
|
||||||
|
|
||||||
|
//刷新字典项值列表
|
||||||
|
function reloadTable() {
|
||||||
|
tableRef.value.reload({ pageNo: 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
//加载字典项值列表;
|
||||||
|
const loadDataTable = async (res) => {
|
||||||
|
const result = await getConfigList({ ...params.value, ...res });
|
||||||
|
configId.value = result?.records[0]?.id
|
||||||
|
configItemShow.value = true
|
||||||
|
nextTick(() => {
|
||||||
|
const tables = tableRef.value.getTableRef();
|
||||||
|
tables.setCurrentRow(result?.records[0])
|
||||||
|
})
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
//删除字典项
|
||||||
async function handleDelete(record: Recordable) {
|
async function handleDelete(record: Recordable) {
|
||||||
let ids = []
|
let ids = []
|
||||||
if (!record) {
|
if (!record) {
|
||||||
@ -153,5 +133,10 @@ function onSelectionChange(value){
|
|||||||
selectionData.value = value
|
selectionData.value = value
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
<style lang="scss" scoped></style>
|
.card-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
import { FormSchema } from '@/components/Form/index';
|
|
||||||
export const schemas: FormSchema[] = [
|
|
||||||
{
|
|
||||||
field: 'name',
|
|
||||||
component: 'Input',
|
|
||||||
label: '配置名称',
|
|
||||||
componentProps: {
|
|
||||||
placeholder: '请输入配置名称',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
];
|
|
Loading…
Reference in New Issue
Block a user