366 lines
9.8 KiB
Vue
366 lines
9.8 KiB
Vue
<!-- 配置编辑弹窗 -->
|
|
<template>
|
|
<ele-modal
|
|
form
|
|
destroy-on-close
|
|
:width="980"
|
|
v-model="visible"
|
|
:title="isUpdate ? '修改配置' : '添加配置'"
|
|
>
|
|
<el-form
|
|
ref="formRef"
|
|
:model="form"
|
|
:rules="rules"
|
|
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
|
|
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
|
|
clearable
|
|
:maxlength="20"
|
|
v-model="form.title"
|
|
placeholder="请输入配置标题(一般由中文组成,仅用于显示)"
|
|
/>
|
|
</el-form-item>
|
|
<template v-if="form.type">
|
|
<el-form-item
|
|
label="配置名称"
|
|
prop="name"
|
|
v-if="HIDE_FORM_ITEM_WHERE.name()"
|
|
>
|
|
<el-input
|
|
clearable
|
|
:maxlength="20"
|
|
v-model="form.name"
|
|
placeholder="请输入配置名称"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item
|
|
label="配置值"
|
|
v-if="HIDE_FORM_ITEM_WHERE.value()"
|
|
>
|
|
<el-input
|
|
:rows="4"
|
|
type="textarea"
|
|
v-model="form.value"
|
|
placeholder="请输入配置值"
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item
|
|
label="配置项"
|
|
v-if="HIDE_FORM_ITEM_WHERE.option()"
|
|
>
|
|
<el-input
|
|
:rows="4"
|
|
type="textarea"
|
|
v-model="form.option"
|
|
placeholder="请输入配置项"
|
|
/>
|
|
</el-form-item>
|
|
|
|
</template>
|
|
</el-col>
|
|
<el-col :span="11" :offset="1">
|
|
<el-form-item label="BIND" prop="itemBind">
|
|
<el-input
|
|
:rows="4"
|
|
type="textarea"
|
|
v-model="form.itemBind"
|
|
placeholder=""
|
|
/>
|
|
</el-form-item>
|
|
<el-form-item label="Class" prop="itemClass">
|
|
<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-card header="样式预览:" style="margin-bottom: 30px;" v-if="form.type && HIDE_FORM_ITEM_WHERE.preview()">
|
|
<config-form-item
|
|
:name="preview.name"
|
|
:title="preview.title"
|
|
:type="preview.type"
|
|
:value="preview.value"
|
|
:option="preview.option"
|
|
:item-bind="preview.bind"
|
|
:key="preview.id"
|
|
/>
|
|
<el-form-item v-if="preview.tips">
|
|
<ele-text type="placeholder" style="line-height: 1.6">
|
|
{{ preview.tips }}
|
|
</ele-text>
|
|
</el-form-item>
|
|
</el-card>
|
|
</el-col>
|
|
</el-row>
|
|
<el-form-item label="配置说明" v-if="HIDE_FORM_ITEM_WHERE.tips()">
|
|
<el-input
|
|
type="textarea"
|
|
v-model="form.tips"
|
|
placeholder="请输入配置说明(在配置页简短提示作用)"
|
|
/>
|
|
</el-form-item>
|
|
<el-divider/>
|
|
<el-form-item label="备注">
|
|
<el-input
|
|
type="textarea"
|
|
v-model="form.comments"
|
|
placeholder="请输入备注(详细描述此配置的功能和作用) - 此备注仅开发人员可见"
|
|
/>
|
|
</el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<el-button @click="handleCancel">取消</el-button>
|
|
<el-button type="primary" :loading="loading" @click="save">
|
|
保存
|
|
</el-button>
|
|
</template>
|
|
</ele-modal>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import {ref, 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, checkExistence} from '@/api/system/config';
|
|
import ConfigSelect from './config-select.vue';
|
|
import {ItemType, getItemLabel} from '@/enum/config-item-type.ts';
|
|
import ConfigFormItem from "@/views/system/config-set/components/config-form-item.vue";
|
|
import {strToBind, strToOption} from "@/utils/sys-config";
|
|
|
|
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
|
|
},
|
|
tips: () => {
|
|
return ['separator', 'alert', 'card', 'collapse','tabs'].indexOf(<string>form.type) == -1
|
|
},
|
|
preview: ()=>{
|
|
return ['tabs', 'tabs_item','card', 'collapse', 'alert', 'separator','json'].indexOf(<string>form.type) == -1
|
|
}
|
|
};
|
|
const preview = computed(() => {
|
|
return {
|
|
...form,
|
|
bind: strToBind(<string>form.type, <string>form.itemBind),
|
|
option: strToOption(<string>form.type, <string>form.option)
|
|
}
|
|
})
|
|
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;
|
|
}>();
|
|
|
|
const emit = defineEmits<{
|
|
(e: 'done'): void;
|
|
}>();
|
|
|
|
/** 弹窗是否打开 */
|
|
const visible = defineModel({type: Boolean});
|
|
|
|
/** 是否是修改 */
|
|
const isUpdate = ref(false);
|
|
|
|
/** 提交状态 */
|
|
const loading = ref(false);
|
|
|
|
/** 表单实例 */
|
|
const formRef = ref<FormInstance | null>(null);
|
|
|
|
interface ConfigEdit extends Config {
|
|
_type_readonly: boolean;
|
|
}
|
|
|
|
/** 表单数据 */
|
|
const [form, resetFields, assignFields] = useFormData<ConfigEdit>({
|
|
id: void 0,
|
|
pid: 0,
|
|
_type_readonly: false,
|
|
type: '',
|
|
comments: '',
|
|
group: '',
|
|
title: '',
|
|
name: '',
|
|
tips: '',
|
|
option: '',
|
|
value: '',
|
|
itemBind: '',
|
|
itemStyle: '',
|
|
itemClass: ''
|
|
});
|
|
|
|
/** 表单验证规则 */
|
|
const rules = computed<FormRules>(() => {
|
|
const obj: FormRules = {
|
|
title: [
|
|
{
|
|
required: true,
|
|
type: 'string',
|
|
message: '请输入标题',
|
|
trigger: 'blur'
|
|
}
|
|
],
|
|
name: [
|
|
{
|
|
required: true,
|
|
message: '请输入配置名称',
|
|
type: 'string',
|
|
trigger: 'blur'
|
|
},
|
|
{
|
|
type: 'string',
|
|
trigger: 'blur',
|
|
validator: (_rule: any, value: string, callback: any) => {
|
|
checkExistence('name', value, isUpdate.value ? props.data.id : null)
|
|
.then(() => {
|
|
callback(new Error('配置名称已经存在'));
|
|
})
|
|
.catch(() => {
|
|
callback();
|
|
});
|
|
}
|
|
}
|
|
],
|
|
itemBind: [
|
|
{
|
|
type: 'string',
|
|
validator: (_rule: any, value: string, callback: any) => {
|
|
if (value) {
|
|
const msg = '请输入正确的JSON格式';
|
|
try {
|
|
const obj = JSON.parse(value);
|
|
if (obj == null || typeof obj !== 'object') {
|
|
callback(msg);
|
|
return;
|
|
}
|
|
} catch (_e) {
|
|
callback(msg);
|
|
return;
|
|
}
|
|
}
|
|
callback();
|
|
},
|
|
trigger: 'blur'
|
|
}
|
|
],
|
|
|
|
};
|
|
return obj;
|
|
});
|
|
|
|
/** 关闭弹窗 */
|
|
const handleCancel = () => {
|
|
visible.value = false;
|
|
};
|
|
|
|
/** 保存编辑 */
|
|
const save = () => {
|
|
formRef.value?.validate?.((valid) => {
|
|
if (!valid) {
|
|
return;
|
|
}
|
|
loading.value = true;
|
|
const saveOrUpdate = isUpdate.value ? updateConfig : addConfig;
|
|
saveOrUpdate(form)
|
|
.then((msg) => {
|
|
loading.value = false;
|
|
EleMessage.success({message: msg, plain: true});
|
|
handleCancel();
|
|
emit('done');
|
|
})
|
|
.catch((e) => {
|
|
loading.value = false;
|
|
EleMessage.error({message: e.message, plain: true});
|
|
});
|
|
});
|
|
};
|
|
|
|
/** 监听弹窗打开 */
|
|
watch(visible, () => {
|
|
if (visible.value) {
|
|
if (props.data) {
|
|
assignFields(props.data);
|
|
isUpdate.value = true;
|
|
} 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 (['tabs_item','tabs'].indexOf(form.type) != -1) {
|
|
form._type_readonly = true;
|
|
}
|
|
form.group = props.group;
|
|
}
|
|
});
|
|
</script>
|