up.
This commit is contained in:
parent
907eb67dc7
commit
5acd35774f
@ -16,9 +16,9 @@ class ConfigController extends BaseController
|
||||
'group'=> $this->request->get('group/s','')
|
||||
]);
|
||||
|
||||
$list = CurdService::getList($this->request, $model)->toArray();
|
||||
$data = CurdService::getList($this->request, $model)->toArray();
|
||||
|
||||
$data = list_build_tree($list);
|
||||
// $data = list_build_tree($list);
|
||||
|
||||
return $this->writeSuccess('success', $data);
|
||||
}
|
||||
@ -43,9 +43,9 @@ class ConfigController extends BaseController
|
||||
'comments' => '',
|
||||
'group'=> ''
|
||||
]);
|
||||
$data['item_bind'] = $this->request->post('itemBind');
|
||||
$data['item_style'] = $this->request->post('itemStyle');
|
||||
$data['item_class'] = $this->request->post('itemClass');
|
||||
$data['item_bind'] = $this->request->post('itemBind','{}');
|
||||
$data['item_style'] = $this->request->post('itemStyle','');
|
||||
$data['item_class'] = $this->request->post('itemClass','');
|
||||
|
||||
|
||||
$user = new SysConfig();
|
||||
|
||||
@ -19,7 +19,7 @@ export async function configData(params: ConfigParam) {
|
||||
/**
|
||||
* 查询配置列表
|
||||
*/
|
||||
export async function listConfig(params?: ConfigParam) {
|
||||
export async function listConfigs(params?: ConfigParam) {
|
||||
const res = await request.get<ApiResult<Config[]>>('/system/config', {
|
||||
params
|
||||
});
|
||||
@ -29,7 +29,6 @@ export async function listConfig(params?: ConfigParam) {
|
||||
return Promise.reject(new Error(res.data.message));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 添加配置
|
||||
*/
|
||||
@ -56,19 +55,23 @@ export async function updateConfig(data: Config) {
|
||||
* 修改配置状态
|
||||
*/
|
||||
export async function updateConfigStatus(id: number, status: number) {
|
||||
const res = await request.put<ApiResult<unknown>>('/system/config/status', {id, status});
|
||||
const res = await request.put<ApiResult<unknown>>('/system/config/status', {
|
||||
id,
|
||||
status
|
||||
});
|
||||
if (res.data.code === 0) {
|
||||
return res.data.message;
|
||||
}
|
||||
return Promise.reject(new Error(res.data.message));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 批量删除配置
|
||||
*/
|
||||
export async function removeConfigs(ids: number[]) {
|
||||
const res = await request.delete<ApiResult<unknown>>('/system/config/batch', {data: ids});
|
||||
const res = await request.delete<ApiResult<unknown>>('/system/config/batch', {
|
||||
data: ids
|
||||
});
|
||||
if (res.data.code === 0) {
|
||||
return res.data.message;
|
||||
}
|
||||
|
||||
@ -4,12 +4,17 @@ import type { PageParam } from '@/api';
|
||||
* 角色
|
||||
*/
|
||||
export interface Config {
|
||||
|
||||
id?: number;
|
||||
pid?: number;
|
||||
title?: string;
|
||||
type?: string;
|
||||
comments?: string;
|
||||
itemStyle?: string;
|
||||
itemBind?: string;
|
||||
itemClass?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 角色搜索条件
|
||||
*/
|
||||
export interface ConfigParam extends PageParam {
|
||||
|
||||
}
|
||||
export interface ConfigParam extends PageParam {}
|
||||
|
||||
@ -2,50 +2,51 @@
|
||||
* 配置类型
|
||||
*/
|
||||
export enum ItemType {
|
||||
SEPARATOR = "-",
|
||||
ALERT = "alert",
|
||||
CARD = "card",
|
||||
COLLAPSE = "collapse",
|
||||
TABS = "tabs",
|
||||
TEXT = "text",
|
||||
TEXTAREA = "textarea",
|
||||
PASSWORD = "password",
|
||||
CHECKBOX = "checkbox",
|
||||
RADIO = "radio",
|
||||
DATE = "date",
|
||||
DATETIME = "datetime",
|
||||
TIME = "time",
|
||||
SWITCH = "switch",
|
||||
HIDDEN = "hidden",
|
||||
RANGE = "range",
|
||||
DATE_RANGE = "date_range",
|
||||
DATETIME_RANGE = "datetime_range",
|
||||
TIME_RANGE = "time_range",
|
||||
NUMBER = "number"
|
||||
SEPARATOR = 'separator',
|
||||
ALERT = 'alert',
|
||||
CARD = 'card',
|
||||
COLLAPSE = 'collapse',
|
||||
TABS = 'tabs',
|
||||
TABS_ITEM = 'tabs_item',
|
||||
TEXT = 'text',
|
||||
TEXTAREA = 'textarea',
|
||||
PASSWORD = 'password',
|
||||
CHECKBOX = 'checkbox',
|
||||
RADIO = 'radio',
|
||||
DATE = 'date',
|
||||
DATETIME = 'datetime',
|
||||
TIME = 'time',
|
||||
SWITCH = 'switch',
|
||||
HIDDEN = 'hidden',
|
||||
RANGE = 'range',
|
||||
DATE_RANGE = 'date_range',
|
||||
DATETIME_RANGE = 'datetime_range',
|
||||
TIME_RANGE = 'time_range',
|
||||
NUMBER = 'number'
|
||||
}
|
||||
|
||||
export const ItemLabels: Record<ItemType, string> = {
|
||||
[ItemType.SEPARATOR]: "分割线",
|
||||
[ItemType.ALERT]: "提示",
|
||||
[ItemType.CARD]: "卡片",
|
||||
[ItemType.COLLAPSE]: "折叠面板",
|
||||
[ItemType.TABS]: "Tabs",
|
||||
[ItemType.TEXT]: "单行文本",
|
||||
[ItemType.TEXTAREA]: "多行文本",
|
||||
[ItemType.PASSWORD]: "密码",
|
||||
[ItemType.CHECKBOX]: "复选框",
|
||||
[ItemType.RADIO]: "单选按钮",
|
||||
[ItemType.DATE]: "日期",
|
||||
[ItemType.DATETIME]: "日期+时间",
|
||||
[ItemType.TIME]: "时间",
|
||||
[ItemType.SWITCH]: "开关",
|
||||
[ItemType.HIDDEN]: "隐藏",
|
||||
[ItemType.TIME_SECOND]: "时间",
|
||||
[ItemType.RANGE]: "范围",
|
||||
[ItemType.DATE_RANGE]: "日期范围",
|
||||
[ItemType.DATETIME_RANGE]: "日期时间范围",
|
||||
[ItemType.TIME_RANGE]: "时间范围",
|
||||
[ItemType.NUMBER]: "数字",
|
||||
[ItemType.SEPARATOR]: '分割线',
|
||||
[ItemType.ALERT]: '提示',
|
||||
[ItemType.CARD]: '卡片',
|
||||
[ItemType.COLLAPSE]: '折叠面板',
|
||||
[ItemType.TABS]: 'Tabs',
|
||||
[ItemType.TABS_ITEM]: 'Tabs子项',
|
||||
[ItemType.TEXT]: '单行文本',
|
||||
[ItemType.TEXTAREA]: '多行文本',
|
||||
[ItemType.PASSWORD]: '密码',
|
||||
[ItemType.CHECKBOX]: '复选框',
|
||||
[ItemType.RADIO]: '单选按钮',
|
||||
[ItemType.DATE]: '日期',
|
||||
[ItemType.DATETIME]: '日期+时间',
|
||||
[ItemType.TIME]: '时间',
|
||||
[ItemType.SWITCH]: '开关',
|
||||
[ItemType.HIDDEN]: '隐藏',
|
||||
[ItemType.RANGE]: '范围',
|
||||
[ItemType.DATE_RANGE]: '日期范围',
|
||||
[ItemType.DATETIME_RANGE]: '日期时间范围',
|
||||
[ItemType.TIME_RANGE]: '时间范围',
|
||||
[ItemType.NUMBER]: '数字'
|
||||
};
|
||||
|
||||
export function getItemLabel(type: ItemType): string {
|
||||
|
||||
@ -1,34 +1,54 @@
|
||||
<template>
|
||||
<template v-for="config in configList">
|
||||
<template v-if="config.type === '-'">
|
||||
<el-divider v-bind="config.bind">{{config.title}}</el-divider>
|
||||
<template v-if="config.type === 'separator'">
|
||||
<el-divider v-bind="config.bind">{{ config.title }}</el-divider>
|
||||
</template>
|
||||
<template v-else-if="config.type === 'alert'">
|
||||
<el-alert :title="config.title" v-bind="config.bind" />
|
||||
</template>
|
||||
<template v-else-if="config.type === 'card'">
|
||||
<ele-card shadow="always" :header="config.title" v-bind="config.bind">
|
||||
<config-form-list :config-list="config.children" v-if="config.children && config.children.length > 0" />
|
||||
<config-form-list
|
||||
:config-list="config.children"
|
||||
v-if="config.children && config.children.length > 0"
|
||||
/>
|
||||
</ele-card>
|
||||
</template>
|
||||
<template v-else-if="config.type === 'collapse'">
|
||||
<el-collapse v-bind="config.bind">
|
||||
<el-collapse-item :title="config.title">
|
||||
<config-form-list :config-list="config.children" v-if="config.children && config.children.length > 0" />
|
||||
<config-form-list
|
||||
:config-list="config.children"
|
||||
v-if="config.children && config.children.length > 0"
|
||||
/>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</template>
|
||||
<template v-else-if="config.type === 'tabs'">
|
||||
<el-tabs
|
||||
type="card"
|
||||
:model-value="defaultTabs(config)"
|
||||
<el-tabs type="card" :model-value="defaultTabs(config)">
|
||||
<el-tab-pane
|
||||
v-for="tabPane in config.children"
|
||||
:label="tabPane.title"
|
||||
:name="tabPane.id"
|
||||
:key="tabPane.id"
|
||||
>
|
||||
<el-tab-pane v-for="(label, name) in config.option" :label="label" :name="name">{{label}}</el-tab-pane>
|
||||
<config-form-list
|
||||
:config-list="tabPane.children"
|
||||
v-if="tabPane.children && tabPane.children.length > 0"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</template>
|
||||
<template v-else>
|
||||
<config-form-item :name="config.name" :title="config.title" :type="config.type" :value="config.value"
|
||||
:option="config.option" :item-bind="config.bind"/>
|
||||
<config-form-item
|
||||
:name="config.name"
|
||||
:title="config.title"
|
||||
:type="config.type"
|
||||
:value="config.value"
|
||||
:option="config.option"
|
||||
:item-bind="config.bind"
|
||||
:key="config.id"
|
||||
/>
|
||||
<el-form-item v-if="config.tips">
|
||||
<ele-text type="placeholder" style="line-height: 1.6">
|
||||
{{ config.tips }}
|
||||
@ -39,15 +59,15 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ConfigFormItem from "../components/config-form-item.vue";
|
||||
const props = defineProps<{
|
||||
import ConfigFormItem from '../components/config-form-item.vue';
|
||||
const props = defineProps<{
|
||||
configList: any;
|
||||
}>();
|
||||
const defaultTabs = (cfg: any)=>{
|
||||
let keys = Object.keys(cfg.option)
|
||||
if(keys.length > 0) {
|
||||
}>();
|
||||
const defaultTabs = (cfg: any) => {
|
||||
let keys = Object.keys(cfg.option);
|
||||
if (keys.length > 0) {
|
||||
return keys[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -9,14 +9,11 @@
|
||||
>
|
||||
刷新
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
class="ele-btn-icon"
|
||||
:icon="Refresh"
|
||||
>
|
||||
<el-button type="danger" class="ele-btn-icon" :icon="Refresh">
|
||||
同步配置
|
||||
</el-button>
|
||||
</el-card>
|
||||
|
||||
<ele-card :body-style="{ paddingTop: '8px' }" v-loading="configLoading">
|
||||
<template #header>
|
||||
<ele-tabs
|
||||
@ -32,7 +29,10 @@
|
||||
label-position="top"
|
||||
@submit.prevent=""
|
||||
>
|
||||
<config-form-list :config-list="configList" v-if="configList.length > 0" />
|
||||
<config-form-list
|
||||
:config-list="configList"
|
||||
v-if="configList.length > 0"
|
||||
/>
|
||||
</el-form>
|
||||
</ele-card>
|
||||
</ele-page>
|
||||
@ -40,12 +40,13 @@
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {onMounted, ref} from 'vue';
|
||||
import {Refresh} from "@element-plus/icons-vue"
|
||||
import {listConfig} from "@/api/system/config";
|
||||
import {getSysConfig, strToBind, strToOption} from "@/utils/sys-config";
|
||||
import {useFormData} from "@/utils/use-form-data";
|
||||
import type {Config} from "@/api/system/config/model";
|
||||
import ConfigFormList from "./components/config-form-list.vue";
|
||||
import {Refresh} from '@element-plus/icons-vue';
|
||||
import {listConfigs} from '@/api/system/config';
|
||||
import {getSysConfig, strToBind, strToOption} from '@/utils/sys-config';
|
||||
import {useFormData} from '@/utils/use-form-data';
|
||||
import type {Config} from '@/api/system/config/model';
|
||||
import ConfigFormList from './components/config-form-list.vue';
|
||||
import {toTree} from 'ele-admin-plus';
|
||||
|
||||
defineOptions({name: 'SystemConfigSet'});
|
||||
|
||||
@ -56,129 +57,37 @@ const configLoading = ref(false);
|
||||
/** 搜索 */
|
||||
const reload = () => {
|
||||
configLoading.value = true;
|
||||
listConfig({group: configGroup.value, limit: 999}).then((data) => {
|
||||
const configs = data.filter(d => d.type !== 'hidden');
|
||||
listConfigs({group: configGroup.value, limit: 999}).then((data) => {
|
||||
const configs = data.filter((d) => d.type !== 'hidden');
|
||||
|
||||
configList.value = configs.map(d=>{
|
||||
const lists = configs.map((d) => {
|
||||
// 解析vBind属性到item
|
||||
d.bind = strToBind(d.type, d.itemBind);
|
||||
d.option = strToOption(d.type, d.option);
|
||||
if(d.type == "tabs") {
|
||||
d.children = [
|
||||
{
|
||||
"id": 6,
|
||||
"pid": 0,
|
||||
"name": "page1",
|
||||
"title": "YEM1",
|
||||
"group": "base",
|
||||
"type": "tab-item",
|
||||
"value": "123456",
|
||||
"options": "",
|
||||
"tips": "",
|
||||
"sort": 100,
|
||||
"status": 1,
|
||||
"vBind": null,
|
||||
"createTime": "2025-08-22 16:50:23",
|
||||
"updateTime": "2025-08-22 16:50:23",
|
||||
"deleteTime": null,
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"pid": 0,
|
||||
"name": "page2",
|
||||
"title": "YEM2",
|
||||
"group": "base",
|
||||
"type": "tab-item",
|
||||
"value": "123456",
|
||||
"options": "",
|
||||
"tips": "",
|
||||
"sort": 100,
|
||||
"status": 1,
|
||||
"vBind": null,
|
||||
"createTime": "2025-08-22 16:50:23",
|
||||
"updateTime": "2025-08-22 16:50:23",
|
||||
"deleteTime": null
|
||||
},
|
||||
];
|
||||
}
|
||||
if(d.type =='card' || d.type == 'collapse'){
|
||||
d.children = [
|
||||
{
|
||||
"id": 6,
|
||||
"pid": 0,
|
||||
"name": "test_password",
|
||||
"title": "系统密码",
|
||||
"group": "base",
|
||||
"type": "password",
|
||||
"value": "123456",
|
||||
"options": "",
|
||||
"tips": "",
|
||||
"sort": 100,
|
||||
"status": 1,
|
||||
"vBind": null,
|
||||
"createTime": "2025-08-22 16:50:23",
|
||||
"updateTime": "2025-08-22 16:50:23",
|
||||
"deleteTime": null
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"pid": 0,
|
||||
"name": "test_textarea",
|
||||
"title": "测试配置",
|
||||
"group": "base",
|
||||
"type": "textarea",
|
||||
"value": "测试配置",
|
||||
"options": "",
|
||||
"tips": "",
|
||||
"sort": 100,
|
||||
"status": 1,
|
||||
"vBind": null,
|
||||
"createTime": "2025-08-22 15:40:19",
|
||||
"updateTime": "2025-08-22 16:40:31",
|
||||
"deleteTime": null
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"pid": 0,
|
||||
"name": "test_text",
|
||||
"title": "站点名称",
|
||||
"group": "base",
|
||||
"type": "text",
|
||||
"value": "Ele Admin Plus",
|
||||
"options": "",
|
||||
"tips": "站点名称显示在<header>的title上",
|
||||
"sort": 100,
|
||||
"status": 1,
|
||||
"vBind": null,
|
||||
"createTime": "2025-08-22 14:11:22",
|
||||
"updateTime": "2025-08-22 16:50:32",
|
||||
"deleteTime": null
|
||||
}
|
||||
];
|
||||
for(let a in d.children){
|
||||
d.children[a].bind = strToBind(d.children[a].type, d.children[a].itemBind);
|
||||
d.children[a].option = strToOption(d.children[a].type, d.children[a].option);
|
||||
}
|
||||
}
|
||||
return d;
|
||||
});
|
||||
configList.value = toTree({
|
||||
data: lists,
|
||||
idField: 'id',
|
||||
parentIdField: 'pid'
|
||||
});
|
||||
configLoading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const groupItems = ref([]);
|
||||
const configGroup = ref("");
|
||||
const configGroup = ref('');
|
||||
onMounted(async () => {
|
||||
// 配置分组
|
||||
const group = [];
|
||||
const {valueData} = await getSysConfig("config_group");
|
||||
const {valueData} = await getSysConfig('config_group');
|
||||
for (const name in valueData) {
|
||||
group.push({name: name, label: valueData[name]})
|
||||
group.push({name: name, label: valueData[name]});
|
||||
}
|
||||
groupItems.value = group
|
||||
groupItems.value = group;
|
||||
if (group.length > 0) {
|
||||
configGroup.value = group[0].name
|
||||
configGroup.value = group[0].name;
|
||||
}
|
||||
reload();
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<ele-modal
|
||||
form
|
||||
destroy-on-close
|
||||
:width="460"
|
||||
:width="960"
|
||||
v-model="visible"
|
||||
:title="isUpdate ? '修改配置' : '添加配置'"
|
||||
>
|
||||
@ -14,40 +14,26 @@
|
||||
label-width="80px"
|
||||
@submit.prevent=""
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="上级" prop="pid">
|
||||
<config-select :model-value="form.pid" :group="form.group" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="类型" prop="type">
|
||||
<el-select
|
||||
clearable
|
||||
class="ele-fluid"
|
||||
placeholder="请选择类型"
|
||||
v-model="form.type"
|
||||
:disabled="form._type_readonly"
|
||||
>
|
||||
<el-option value="-" label="分割线" />
|
||||
<el-option value="alert" label="提示" />
|
||||
<el-option value="card" label="卡片" />
|
||||
<el-option value="collapse" label="折叠面板" />
|
||||
<el-option value="tabs" label="Tabs" />
|
||||
<el-option value="tabs_item" label="Tabs子页" />
|
||||
<el-option value="text" label="单行文本" />
|
||||
<el-option value="textarea" label="多行文本" />
|
||||
<el-option value="password" label="密码" />
|
||||
<el-option value="checkbox" label="复选框" />
|
||||
<el-option value="radio" label="单选按钮" />
|
||||
<el-option value="date" label="日期" />
|
||||
<el-option value="datetime" label="日期+时间" />
|
||||
<el-option value="time" label="时间" />
|
||||
<el-option value="switch" label="开关" />
|
||||
<el-option value="hidden" label="隐藏" />
|
||||
<el-option value="range" label="范围" />
|
||||
<el-option value="date_range" label="日期范围" />
|
||||
<el-option value="datetime_range" label="日期时间范围" />
|
||||
<el-option value="time_range" label="时间范围" />
|
||||
<el-option value="number" label="数字" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="配置PID" prop="pid">
|
||||
<el-input-number
|
||||
v-model="form.pid"
|
||||
<el-option
|
||||
v-for="label in configItemType"
|
||||
:value="label"
|
||||
:label="getItemLabel(label)"
|
||||
:key="label"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="配置标题" prop="title">
|
||||
<el-input
|
||||
@ -57,7 +43,12 @@
|
||||
placeholder="请输入配置标题(一般由中文组成,仅用于显示)"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="配置名称" prop="name">
|
||||
<template v-if="form.type">
|
||||
<el-form-item
|
||||
label="配置名称"
|
||||
prop="name"
|
||||
v-if="HIDE_FORM_ITEM_WHERE.name()"
|
||||
>
|
||||
<el-input
|
||||
clearable
|
||||
:maxlength="20"
|
||||
@ -65,10 +56,10 @@
|
||||
placeholder="请输入配置名称"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<!-- //由英文字母和下划线组成,如 web_site_title,调用方法:config('web_site_title')-->
|
||||
|
||||
<el-form-item label="配置值">
|
||||
<el-form-item
|
||||
label="配置值"
|
||||
v-if="HIDE_FORM_ITEM_WHERE.value()"
|
||||
>
|
||||
<el-input
|
||||
:rows="4"
|
||||
type="textarea"
|
||||
@ -76,7 +67,10 @@
|
||||
placeholder="请输入配置值"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="配置项">
|
||||
<el-form-item
|
||||
label="配置项"
|
||||
v-if="HIDE_FORM_ITEM_WHERE.option()"
|
||||
>
|
||||
<el-input
|
||||
:rows="4"
|
||||
type="textarea"
|
||||
@ -84,14 +78,6 @@
|
||||
placeholder="请输入配置项"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Bind属性">
|
||||
<el-input
|
||||
:rows="4"
|
||||
type="textarea"
|
||||
v-model="form.bind"
|
||||
placeholder="请输入Bind属性"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="配置说明">
|
||||
<el-input
|
||||
:rows="4"
|
||||
@ -100,7 +86,36 @@
|
||||
placeholder="请输入配置说明"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
</template>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="BIND">
|
||||
<el-input
|
||||
:rows="4"
|
||||
type="textarea"
|
||||
v-model="form.itemBind"
|
||||
placeholder=""
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Class">
|
||||
<el-input
|
||||
type="text"
|
||||
v-model="form.itemClass"
|
||||
placeholder="请输入渲染框CSS样式类"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="Style">
|
||||
<el-input
|
||||
:rows="4"
|
||||
type="textarea"
|
||||
v-model="form.itemStyle"
|
||||
placeholder="请输入渲染框Style样式"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<el-form-item label="备注" v-if="false">
|
||||
<el-input
|
||||
:rows="4"
|
||||
type="textarea"
|
||||
@ -119,16 +134,51 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, watch } from 'vue';
|
||||
import { ref, reactive, watch, computed } from 'vue';
|
||||
import type { FormInstance, FormRules } from 'element-plus';
|
||||
import { EleMessage } from 'ele-admin-plus';
|
||||
import { useFormData } from '@/utils/use-form-data';
|
||||
import type { Config } from '@/api/system/config/model';
|
||||
import {addConfig, updateConfig} from "@/api/system/config";
|
||||
|
||||
import { addConfig, updateConfig } from '@/api/system/config';
|
||||
import ConfigSelect from './config-select.vue';
|
||||
import { ItemType, getItemLabel } from '@/enum/config-item-type.ts';
|
||||
const HIDE_FORM_ITEM_WHERE: any = {
|
||||
name: () => {
|
||||
return ['tabs', 'tabs_item','alert','card','separator'].indexOf(<string>form.type) == -1;
|
||||
},
|
||||
value: ()=>{
|
||||
return ['tabs', 'tabs_item'].indexOf(<string>form.type) == -1
|
||||
},
|
||||
option: ()=>{
|
||||
return ['tabs', 'tabs_item'].indexOf(<string>form.type) == -1
|
||||
}
|
||||
};
|
||||
const configItemType: any = computed(() => {
|
||||
let list = {};
|
||||
if (props.parent) {
|
||||
if (props.parent.type == 'tabs') {
|
||||
list[ItemType.TABS_ITEM] = ItemType.TABS_ITEM;
|
||||
} else if (props.parent.type == 'tabs_item') {
|
||||
for (const name in ItemType) {
|
||||
if (
|
||||
[ItemType.TABS_ITEM, ItemType.TABS].indexOf(ItemType[name]) == -1
|
||||
) {
|
||||
list[name] = ItemType[name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Object.keys(list).length == 0) {
|
||||
return ItemType;
|
||||
} else {
|
||||
return list;
|
||||
}
|
||||
});
|
||||
const props = defineProps<{
|
||||
/** 修改回显的数据 */
|
||||
data?: Config | null;
|
||||
/** 父级元素 */
|
||||
parent?: Config | null;
|
||||
/** 配置所属组 */
|
||||
group?: string | null;
|
||||
}>();
|
||||
@ -149,18 +199,26 @@
|
||||
/** 表单实例 */
|
||||
const formRef = ref<FormInstance | null>(null);
|
||||
|
||||
interface ConfigEdit extends Config {
|
||||
_type_readonly: boolean;
|
||||
}
|
||||
|
||||
/** 表单数据 */
|
||||
const [form, resetFields, assignFields] = useFormData<Config>({
|
||||
const [form, resetFields, assignFields] = useFormData<ConfigEdit>({
|
||||
id: void 0,
|
||||
pid: 0,
|
||||
_type_readonly: false,
|
||||
type: '',
|
||||
comments: '',
|
||||
group: '',
|
||||
title: '',
|
||||
name: '',
|
||||
type: '',
|
||||
tips: '',
|
||||
option: '',
|
||||
value: '',
|
||||
itemBind: '',
|
||||
itemStyle: '',
|
||||
itemClass: ''
|
||||
});
|
||||
|
||||
/** 表单验证规则 */
|
||||
@ -219,6 +277,17 @@
|
||||
} else {
|
||||
resetFields();
|
||||
isUpdate.value = false;
|
||||
if (props.parent) {
|
||||
let data: any = { pid: props.parent.id };
|
||||
if (props.parent.type == 'tabs') {
|
||||
data.type = 'tabs_item';
|
||||
data._type_readonly = true;
|
||||
}
|
||||
assignFields(data);
|
||||
}
|
||||
}
|
||||
if (form.type == 'tabs_item') {
|
||||
form._type_readonly = true;
|
||||
}
|
||||
form.group = props.group;
|
||||
}
|
||||
|
||||
72
z_ele/src/views/system/config/components/config-select.vue
Normal file
72
z_ele/src/views/system/config/components/config-select.vue
Normal file
@ -0,0 +1,72 @@
|
||||
<!-- 上级配置选择下拉框 -->
|
||||
<template>
|
||||
<el-tree-select
|
||||
clearable
|
||||
filterable
|
||||
:data="configData"
|
||||
check-strictly
|
||||
default-expand-all
|
||||
node-key="id"
|
||||
:props="{ label: 'title', disabled: 'disabled' }"
|
||||
:placeholder="placeholder"
|
||||
:model-value="modelValue || void 0"
|
||||
class="ele-fluid"
|
||||
:popper-options="{ strategy: 'fixed' }"
|
||||
@update:modelValue="updateValue"
|
||||
>
|
||||
<template #default="{ data }">
|
||||
<span>{{ data.title }}</span>
|
||||
</template>
|
||||
</el-tree-select>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import { EleMessage, toTree } from 'ele-admin-plus';
|
||||
import { listConfigs } from '@/api/system/config';
|
||||
import type { Config } from '@/api/system/config/model';
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
/** 选中的配置 */
|
||||
modelValue?: number | string;
|
||||
/** 提示信息 */
|
||||
placeholder?: string;
|
||||
/** 配置所属组 */
|
||||
group?: string | null;
|
||||
}>(),
|
||||
{
|
||||
placeholder: '请选择上级配置'
|
||||
}
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: number | string): void;
|
||||
}>();
|
||||
|
||||
/** 配置数据 */
|
||||
const configData = ref<Config[]>([]);
|
||||
|
||||
/** 更新选中数据 */
|
||||
const updateValue = (value: number | string) => {
|
||||
emit('update:modelValue', value || 0);
|
||||
};
|
||||
|
||||
/** 获取配置数据 */
|
||||
listConfigs({ group: props.group, limit: 999 })
|
||||
.then((list) => {
|
||||
const data: any = list.map((d: Config) => {
|
||||
d.disabled = ['tabs', 'tabs_item'].indexOf(d.type) === -1;
|
||||
return d;
|
||||
});
|
||||
|
||||
configData.value = toTree({
|
||||
data: data.filter(d => !d.disabled),
|
||||
idField: 'id',
|
||||
parentIdField: 'pid'
|
||||
});
|
||||
})
|
||||
.catch((e) => {
|
||||
EleMessage.error({ message: e.message, plain: true });
|
||||
});
|
||||
</script>
|
||||
@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<ele-page>
|
||||
<!-- 搜索表单 -->
|
||||
<config-search @search="reload"/>
|
||||
<config-search @search="reload" />
|
||||
|
||||
<ele-tabs
|
||||
type="card"
|
||||
type="tag"
|
||||
v-model="configGroup"
|
||||
:items="groupItems"
|
||||
@tabChange="reload()"
|
||||
@ -23,6 +23,7 @@
|
||||
:pagination="false"
|
||||
cache-key="systemRoleTable"
|
||||
:load-on-created="false"
|
||||
height="66vh"
|
||||
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
||||
>
|
||||
<template #toolbar>
|
||||
@ -35,22 +36,25 @@
|
||||
添加
|
||||
</el-button>
|
||||
</template>
|
||||
<template #action="d">
|
||||
{{ d }}
|
||||
<!-- <template v-if="['tabs'].indexOf(row.type) != -1">-->
|
||||
<!-- {{ row }}-->
|
||||
<!-- <el-link type="primary" underline="never" @click="openEdit(row)">添加子项</el-link>-->
|
||||
<!-- <el-divider direction="vertical"/>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-link type="primary" underline="never" @click="openEdit(row)">-->
|
||||
<!-- 修改-->
|
||||
<!-- </el-link>-->
|
||||
<!-- <template v-if="row.group != 'system'">-->
|
||||
<!-- <el-divider direction="vertical"/>-->
|
||||
<!-- <el-link type="danger" underline="never" @click="remove(row)">-->
|
||||
<!-- 删除-->
|
||||
<!-- </el-link>-->
|
||||
<!-- </template>-->
|
||||
<template #action="{ row }">
|
||||
<template v-if="['tabs', 'tabs_item', 'collapse', 'card'].indexOf(row.type) != -1">
|
||||
<el-link
|
||||
type="primary"
|
||||
underline="never"
|
||||
@click="openEdit(null, row)"
|
||||
>添加子项</el-link
|
||||
>
|
||||
<el-divider direction="vertical" />
|
||||
</template>
|
||||
<el-link type="primary" underline="never" @click="openEdit(row)">
|
||||
修改
|
||||
</el-link>
|
||||
<template v-if="row.group != 'system'">
|
||||
<el-divider direction="vertical" />
|
||||
<el-link type="danger" underline="never" @click="remove(row)">
|
||||
删除
|
||||
</el-link>
|
||||
</template>
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
<el-switch
|
||||
@ -59,57 +63,75 @@
|
||||
@change="(checked: boolean) => editStatus(checked, row)"
|
||||
/>
|
||||
</template>
|
||||
<template #type="{ row }">
|
||||
<span :title="row.type">{{ getItemLabel(row.type) }}</span>
|
||||
</template>
|
||||
<template #sort="{ row }">
|
||||
<el-input-number :controls="false" v-model="row.sort" :min="1" :max="9999" style="width: 100%;"></el-input-number>
|
||||
</template>
|
||||
</ele-pro-table>
|
||||
</ele-card>
|
||||
<!-- 编辑弹窗 -->
|
||||
<config-edit v-model="showEdit" :data="current" @done="reload" :group="configGroup"/>
|
||||
<config-edit
|
||||
v-model="showEdit"
|
||||
:data="current"
|
||||
:parent="parent"
|
||||
@done="reload"
|
||||
:group="configGroup"
|
||||
/>
|
||||
</ele-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import {onMounted, ref} from 'vue';
|
||||
import {ElMessageBox} from 'element-plus';
|
||||
import {EleMessage} from 'ele-admin-plus';
|
||||
import type {EleProTable} from 'ele-admin-plus';
|
||||
import type {
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { ElMessageBox } from 'element-plus';
|
||||
import {EleMessage, toTree} from 'ele-admin-plus';
|
||||
import type { EleProTable } from 'ele-admin-plus';
|
||||
import type {
|
||||
DatasourceFunction,
|
||||
Columns
|
||||
} from 'ele-admin-plus/es/ele-pro-table/types';
|
||||
import {PlusOutlined,} from '@/components/icons';
|
||||
import ConfigSearch from './components/config-search.vue';
|
||||
import ConfigEdit from './components/config-edit.vue';
|
||||
import type {Config, ConfigParam} from '@/api/system/config/model';
|
||||
import {listConfig, updateConfigStatus, removeConfigs} from "@/api/system/config";
|
||||
import {getSysConfig} from "@/utils/sys-config";
|
||||
} from 'ele-admin-plus/es/ele-pro-table/types';
|
||||
import { PlusOutlined } from '@/components/icons';
|
||||
import ConfigSearch from './components/config-search.vue';
|
||||
import ConfigEdit from './components/config-edit.vue';
|
||||
import type { Config, ConfigParam } from '@/api/system/config/model';
|
||||
import {
|
||||
listConfigs,
|
||||
updateConfigStatus,
|
||||
removeConfigs
|
||||
} from '@/api/system/config';
|
||||
import { getSysConfig } from '@/utils/sys-config';
|
||||
import { ItemType, getItemLabel } from '@/enum/config-item-type.ts';
|
||||
|
||||
defineOptions({name: 'SystemConfig'});
|
||||
defineOptions({ name: 'SystemConfig' });
|
||||
|
||||
/** 表格实例 */
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
/** 表格实例 */
|
||||
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
|
||||
|
||||
/** 表格列配置 */
|
||||
const columns = ref<Columns>([
|
||||
/** 表格列配置 */
|
||||
const columns = ref<Columns>([
|
||||
{
|
||||
type: 'index',
|
||||
columnKey: 'index',
|
||||
width: 50,
|
||||
align: 'center'
|
||||
},
|
||||
{
|
||||
prop: 'name',
|
||||
label: '名称',
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
prop: 'title',
|
||||
label: '标题',
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
prop: 'type',
|
||||
label: '类型',
|
||||
prop: 'name',
|
||||
label: '名称',
|
||||
minWidth: 120
|
||||
},
|
||||
{
|
||||
prop: 'type',
|
||||
slot: 'type',
|
||||
label: '类型',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
prop: 'status',
|
||||
label: '状态',
|
||||
@ -120,8 +142,10 @@ const columns = ref<Columns>([
|
||||
},
|
||||
{
|
||||
prop: 'sort',
|
||||
slot: 'sort',
|
||||
label: '排序',
|
||||
minWidth: 140
|
||||
align: 'center',
|
||||
width: 140
|
||||
},
|
||||
{
|
||||
prop: 'comments',
|
||||
@ -138,47 +162,59 @@ const columns = ref<Columns>([
|
||||
hideInPrint: true,
|
||||
hideInExport: true
|
||||
}
|
||||
]);
|
||||
]);
|
||||
|
||||
/** 表格选中数据 */
|
||||
const selections = ref<Config[]>([]);
|
||||
/** 表格选中数据 */
|
||||
const selections = ref<Config[]>([]);
|
||||
|
||||
/** 当前编辑数据 */
|
||||
const current = ref<Config | null>(null);
|
||||
/** 当前编辑数据 */
|
||||
const current = ref<Config | null>(null);
|
||||
|
||||
/** 是否显示编辑弹窗 */
|
||||
const showEdit = ref(false);
|
||||
const parent = ref<Config | null>(null);
|
||||
|
||||
/** 是否显示编辑弹窗 */
|
||||
const showEdit = ref(false);
|
||||
|
||||
/** 表格数据源 */
|
||||
const datasource: DatasourceFunction = ({pages, where, orders}) => {
|
||||
return listConfig({...where, ...orders, ...pages, group: configGroup.value, limit: 999});
|
||||
};
|
||||
/** 表格数据源 */
|
||||
const datasource: DatasourceFunction = async ({ pages, where, orders }) => {
|
||||
const data = await listConfigs({
|
||||
...where,
|
||||
...orders,
|
||||
...pages,
|
||||
group: configGroup.value,
|
||||
limit: 999
|
||||
});
|
||||
return toTree({
|
||||
data,
|
||||
idField: 'id',
|
||||
parentIdField: 'pid'
|
||||
});
|
||||
};
|
||||
|
||||
/** 搜索 */
|
||||
const reload = (where?: ConfigParam) => {
|
||||
/** 搜索 */
|
||||
const reload = (where?: ConfigParam) => {
|
||||
selections.value = [];
|
||||
tableRef.value?.reload?.({page: 1, where});
|
||||
};
|
||||
tableRef.value?.reload?.({ page: 1, where });
|
||||
};
|
||||
|
||||
/** 打开编辑弹窗 */
|
||||
const openEdit = (row?: Config) => {
|
||||
/** 打开编辑弹窗 */
|
||||
const openEdit = (row?: Config, parentRow?: Config) => {
|
||||
current.value = row ?? null;
|
||||
showEdit.value = true;
|
||||
};
|
||||
parent.value = parentRow;
|
||||
};
|
||||
|
||||
|
||||
/** 删除单个 */
|
||||
const remove = (row?: Config) => {
|
||||
/** 删除单个 */
|
||||
const remove = (row?: Config) => {
|
||||
const rows = row == null ? selections.value : [row];
|
||||
if (!rows.length) {
|
||||
EleMessage.error({message: '请至少选择一条数据', plain: true});
|
||||
EleMessage.error({ message: '请至少选择一条数据', plain: true });
|
||||
return;
|
||||
}
|
||||
ElMessageBox.confirm(
|
||||
'确定要删除“' + rows.map((d) => d.roleName).join(', ') + '”吗?',
|
||||
'系统提示',
|
||||
{type: 'warning', draggable: true}
|
||||
{ type: 'warning', draggable: true }
|
||||
)
|
||||
.then(() => {
|
||||
const loading = EleMessage.loading({
|
||||
@ -188,44 +224,43 @@ const remove = (row?: Config) => {
|
||||
removeConfigs(rows.map((d) => d.id))
|
||||
.then((msg) => {
|
||||
loading.close();
|
||||
EleMessage.success({message: msg, plain: true});
|
||||
EleMessage.success({ message: msg, plain: true });
|
||||
reload();
|
||||
})
|
||||
.catch((e) => {
|
||||
loading.close();
|
||||
EleMessage.error({message: e.message, plain: true});
|
||||
EleMessage.error({ message: e.message, plain: true });
|
||||
});
|
||||
})
|
||||
.catch(() => {
|
||||
});
|
||||
};
|
||||
.catch(() => {});
|
||||
};
|
||||
|
||||
/** 修改配置状态 */
|
||||
const editStatus = (checked: boolean, row: Config) => {
|
||||
/** 修改配置状态 */
|
||||
const editStatus = (checked: boolean, row: Config) => {
|
||||
const status = checked ? 1 : 0;
|
||||
updateConfigStatus(row.id, status)
|
||||
.then((msg) => {
|
||||
row.status = status;
|
||||
EleMessage.success({message: msg, plain: true});
|
||||
EleMessage.success({ message: msg, plain: true });
|
||||
})
|
||||
.catch((e) => {
|
||||
EleMessage.error({message: e.message, plain: true});
|
||||
EleMessage.error({ message: e.message, plain: true });
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
const groupItems = ref([]);
|
||||
const configGroup = ref("");
|
||||
onMounted(async () => {
|
||||
const groupItems = ref([]);
|
||||
const configGroup = ref('');
|
||||
onMounted(async () => {
|
||||
// 配置分组
|
||||
const group = [];
|
||||
const {valueData} = await getSysConfig("config_group");
|
||||
const { valueData } = await getSysConfig('config_group');
|
||||
for (const name in valueData) {
|
||||
group.push({name: name, label: valueData[name]})
|
||||
group.push({ name: name, label: valueData[name] });
|
||||
}
|
||||
groupItems.value = group
|
||||
groupItems.value = group;
|
||||
if (group.length > 0) {
|
||||
configGroup.value = group[0].name
|
||||
configGroup.value = group[0].name;
|
||||
}
|
||||
reload();
|
||||
})
|
||||
});
|
||||
</script>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user