smart-power-ui/src/views/profile/attribute/functionFormModel.vue

750 lines
22 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="function-form-model">
<el-dialog
:close-on-click-modal="false"
:modal="false"
:title="title"
:visible="visible"
class="params-eldialog"
top="5vh"
width="800px"
@close="$emit('update:visible', false)"
>
<el-form
ref="form"
:model="form"
:rules="rules"
label-position="top"
style="padding: 0 15px"
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="标识:" prop="id">
<el-input
v-model="form.id"
placeholder="请输入标识"
@input="inputChange"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="功能名称:" prop="name">
<el-input v-model="form.name" placeholder="请输入功能名称" />
</el-form-item>
</el-col>
</el-row>
<el-form-item label="输入参数:" prop="inputs">
<el-table :data="form.inputs" height="300px">
<el-table-column align="left" label="标识" prop="id" />
<el-table-column align="left" label="参数名称" prop="name" />
<el-table-column align="center" label="是否必选" prop="required">
<template slot-scope="scope">
<span>{{ scope.row.expands.required ? "是" : "否" }}</span>
</template>
</el-table-column>
<el-table-column align="left" label="数据类型" prop="type">
<template slot-scope="scope">
<span>{{ dataTypeOption[scope.row.valueType.type] }}</span>
</template>
</el-table-column>
<el-table-column
align="center"
class-name="small-padding fixed-width"
label="操作"
width="200px"
>
<template slot-scope="scope">
<el-button
:disabled="scope.$index === 0"
icon="el-icon-arrow-up"
size="mini"
type="text"
@click="handleInputUp(scope.$index)"
>上移</el-button>
<el-button
:disabled="scope.$index === form.inputs.length - 1"
icon="el-icon-arrow-down"
size="mini"
type="text"
@click="handleInputDown(scope.$index)"
>下移</el-button>
<el-button
icon="el-icon-edit"
size="mini"
type="text"
@click="handleInputUpdate(scope.row, scope.$index)"
>修改</el-button
>
<el-button
icon="el-icon-delete"
size="mini"
type="text"
@click="handleInputDelete(scope.row, scope.$index)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<el-button
icon="el-icon-plus"
plain
style="width: 100%;margin-top: 10px"
type="info"
@click="addInputParam"
>新增输入参数</el-button
>
</el-form-item>
<el-form-item label="是否异步:" prop="async">
<el-switch v-model="form.async" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="$emit('update:visible', false)">取 消</el-button>
</div>
</el-dialog>
<!-- 输入参数弹窗 -->
<el-dialog
:close-on-click-modal="false"
:visible.sync="inputParamOpen"
append-to-body
class="params-eldialog"
title="输入参数"
width="600px"
@close="handleInputDialogClose"
>
<el-form
ref="inputForm"
:model="inputFormObj.form"
:rules="inputFormRules"
label-position="top"
label-width="100px"
>
<el-form-item label="标识:" prop="id">
<el-input v-model="inputFormObj.form.id" placeholder="请输入标识" />
</el-form-item>
<el-form-item label="参数名称:" prop="name">
<el-input
v-model="inputFormObj.form.name"
placeholder="请输入参数名称"
/>
</el-form-item>
<el-form-item label="数据类型:" prop="type">
<el-select
v-model="inputFormObj.form.valueType.type"
placeholder="请选择数据类型"
style="width: 100%"
@change="inputDataTypeChange"
>
<el-option
v-for="(dice, value) in dataTypeOption"
:key="value"
:label="dice"
:value="value"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="inputFormObj.form.valueType.type === 'enum'"
label="枚举值:"
>
<div class="enum-box">
<div class="enum-header">
<el-button size="mini" type="primary" @click="addEnumItem"
>添加枚举项</el-button
>
</div>
<el-table
:data="inputFormObj.form.valueType.elements"
border
style="width: 100%"
>
<el-table-column
align="center"
label="序号"
type="index"
width="60"
></el-table-column>
<el-table-column label="值" prop="value" width="180">
<template slot-scope="scope">
<el-input
v-model="scope.row.value"
:class="{ 'is-error': scope.row.value }"
placeholder="请输入值"
></el-input>
<div
v-if="scope.row.value === ''"
class="el-form-item__error"
>
值不能为空
</div>
</template>
</el-table-column>
<el-table-column label="描述" prop="text">
<template slot-scope="scope">
<el-input
v-model="scope.row.text"
:class="{ 'is-error': scope.row.text }"
placeholder="请输入描述"
></el-input>
<div v-if="scope.row.text === ''" class="el-form-item__error">
描述不能为空
</div>
</template>
</el-table-column>
<el-table-column align="center" label="操作" width="80">
<template slot-scope="scope">
<el-button
icon="el-icon-delete"
style="color: red"
type="text"
@click="removeEnumItem(scope.$index)"
></el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-form-item>
<el-form-item label="是否必选:" prop="required">
<el-switch v-model="inputFormObj.form.expands.required" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitInputForm">确 定</el-button>
<el-button @click="inputParamOpen = false">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { dataTypeOption } from "@/basedata/physicalModel";
const defaultenumForm = {
value: "",
text: ""
};
const defaultInputForm = {
id: "",
name: "",
expands: {
required: false
},
valueType: {
expands: {},
type: "int",
elements: []
}
};
export default {
name: "FunctionFormModel",
props: {
visible: {
type: Boolean,
default: false
},
title: {
type: String,
default: "新增"
},
row: {
type: Object,
default: () => {}
},
tempType: {
type: String,
default: "add"
},
paramIdx: {
type: Number,
default: -1
},
functionList: {
type: Array,
default: []
}
},
data() {
return {
dataTypeOption,
inputParamOpen: false,
form: {
id: "",
name: "",
expands: {},
async: false,
inputs: [],
output: {}
},
inputFormObj: {
isEdit: false,
index: -1,
form: JSON.parse(JSON.stringify(defaultInputForm))
},
inputFormRules: {
id: [
{ required: true, message: "标识不能为空", trigger: "blur" },
{
pattern: /^[a-zA-Z0-9_\-]+$/,
message: "标识只能由数字、字母、下划线、中划线组成",
trigger: "blur"
},
{ validator: this.validateInputId, trigger: "blur" }
],
name: [{ required: true, message: "参数名称不能为空", trigger: "blur" }]
},
// 表单校验
rules: {
name: [{ required: true, message: "名称不能为空", trigger: "blur" }],
cmdKey: [{ required: true, message: "分组不能为空", trigger: "blur" }],
id: [
{ required: true, message: "标识不能为空", trigger: "blur" },
{
pattern: /^[a-zA-Z0-9_\-]+$/,
message: "标识只能由数字、字母、下划线、中划线组成",
trigger: "blur"
},
{ validator: this.validateFunctionId, trigger: "blur" }
],
type: [{ required: true, message: "数据类型不能为空", trigger: "blur" }]
}
};
},
created() {
if (this.tempType === "update" && this.paramIdx >= 0) {
this.form = JSON.parse(JSON.stringify(this.row));
} else {
// 新增时初始化表单
this.form = {
id: "",
name: "",
expands: {},
async: true,
inputs: [],
output: {}
};
}
},
watch: {
visible(val) {
if (val) {
// 当弹窗打开时
if (this.tempType === "update" && this.paramIdx >= 0) {
// 编辑模式,复制传入的数据
this.form = JSON.parse(JSON.stringify(this.row));
} else {
// 新增模式,重置表单数据
this.form = {
id: "",
name: "",
expands: {},
async: true,
inputs: [],
output: {}
};
}
// 确保输入参数表单也被重置
this.inputFormObj = {
isEdit: false,
index: -1,
form: JSON.parse(JSON.stringify(defaultInputForm))
};
} else {
// 当弹窗关闭时,重置表单校验状态
this.$nextTick(() => {
if (this.$refs.form) {
this.$refs.form.clearValidate();
}
if (this.$refs.inputForm) {
this.$refs.inputForm.clearValidate();
}
});
}
}
},
methods: {
// 自定义标识符验证规则
validateFunctionId(rule, value, callback) {
if (this.tempType === "update" && value === this.row.id) {
// 如果是编辑模式且ID没有变化直接通过验证
callback();
return;
}
// 检查功能标识符是否重复
const isDuplicate =
this.functionList && this.functionList.some(item => item.id === value);
if (isDuplicate) {
callback(new Error("标识符已存在,请更换"));
} else {
callback();
}
},
// 自定义输入参数标识符验证规则
validateInputId(rule, value, callback) {
if (
this.inputFormObj.isEdit &&
value === this.form.inputs[this.inputFormObj.index].id
) {
// 如果是编辑模式且ID没有变化直接通过验证
callback();
return;
}
// 检查输入参数标识符是否重复
const isDuplicate = this.form.inputs.some(item => item.id === value);
if (isDuplicate) {
callback(new Error("输入参数标识符已存在,请更换"));
} else {
callback();
}
},
inputDataTypeChange(val) {
// 根据选择的数据类型设置valueType的type属性
if (val === "int") {
this.inputFormObj.form.valueType.type = "int";
this.inputFormObj.form.valueType.elements = [];
} else if (val === "long") {
this.inputFormObj.form.valueType.type = "long";
this.inputFormObj.form.valueType.elements = [];
} else if (val === "float") {
this.inputFormObj.form.valueType.type = "float";
this.inputFormObj.form.valueType.elements = [];
} else if (val === "double") {
this.inputFormObj.form.valueType.type = "double";
this.inputFormObj.form.valueType.elements = [];
} else if (val === "string") {
this.inputFormObj.form.valueType.type = "string";
this.inputFormObj.form.valueType.elements = [];
} else if (val === "boolean") {
this.inputFormObj.form.valueType.type = "boolean";
this.inputFormObj.form.valueType.elements = [];
} else if (val === "date") {
this.inputFormObj.form.valueType.type = "date";
this.inputFormObj.form.valueType.elements = [];
} else if (val === "enum") {
this.inputFormObj.form.valueType.type = "enum";
if (
!this.inputFormObj.form.valueType.elements ||
this.inputFormObj.form.valueType.elements.length === 0
) {
this.inputFormObj.form.valueType.elements = [];
// 默认添加一个空的枚举项
this.addEnumItem();
}
} else if (val === "array") {
this.inputFormObj.form.valueType.type = "array";
this.inputFormObj.form.valueType.elements = [];
} else if (val === "object") {
this.inputFormObj.form.valueType.type = "object";
this.inputFormObj.form.valueType.elements = [];
} else if (val === "file") {
this.inputFormObj.form.valueType.type = "file";
this.inputFormObj.form.valueType.elements = [];
} else if (val === "password") {
this.inputFormObj.form.valueType.type = "password";
this.inputFormObj.form.valueType.elements = [];
} else if (val === "geoPoint") {
this.inputFormObj.form.valueType.type = "geoPoint";
this.inputFormObj.form.valueType.elements = [];
}
},
addEnumItem() {
// 确保elements数组已初始化
if (!this.inputFormObj.form.valueType.elements) {
this.inputFormObj.form.valueType.elements = [];
}
// 添加一个新的枚举项
const newEnumItem = JSON.parse(JSON.stringify(defaultenumForm));
newEnumItem.value = "";
newEnumItem.text = "";
this.inputFormObj.form.valueType.elements.push(newEnumItem);
},
removeEnumItem(index) {
this.$confirm("是否确认删除该枚举参数?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.inputFormObj.form.valueType.elements.splice(index, 1);
this.$message({
type: "success",
message: "删除成功!"
});
})
.catch(() => {
this.$message({
type: "info",
message: "已取消删除"
});
});
},
// 修改提交方法,增加枚举项验证
submitInputForm() {
// 验证表单
this.$refs.inputForm.validate(valid => {
if (valid) {
// 如果是枚举类型,确保至少有一个枚举项
if (
this.inputFormObj.form.valueType.type === "enum" &&
(!this.inputFormObj.form.valueType.elements ||
this.inputFormObj.form.valueType.elements.length === 0)
) {
this.$message.warning("枚举类型至少需要一个枚举项");
return;
}
// 验证枚举项的值和描述不能为空
if (this.inputFormObj.form.valueType.type === "enum") {
let hasError = false;
const enumValues = new Set();
for (
let i = 0;
i < this.inputFormObj.form.valueType.elements.length;
i++
) {
const item = this.inputFormObj.form.valueType.elements[i];
let value = !item.value;
let text = !item.text;
if (value || text) {
hasError = true;
break;
}
if (enumValues.has(item.value)) {
this.$message.warning(`枚举值 "${item.value}" 重复,请修改`);
return;
}
enumValues.add(item.value);
}
if (hasError) {
this.$message.warning("请完善枚举项的值和描述");
return;
}
}
// 如果是编辑模式
if (this.inputFormObj.isEdit) {
// 更新现有输入参数
this.$set(
this.form.inputs,
this.inputFormObj.index,
this.inputFormObj.form
);
} else {
// 添加新的输入参数
this.form.inputs.push(
JSON.parse(JSON.stringify(this.inputFormObj.form))
);
}
// 关闭弹窗
this.inputParamOpen = false;
// 清除校验状态
this.$nextTick(() => {
this.$refs.inputForm.clearValidate();
});
// 提示成功
this.$message.success(
this.inputFormObj.isEdit ? "修改成功" : "添加成功"
);
}
});
},
addInputParam() {
this.inputFormObj = {
isEdit: false,
index: -1,
form: JSON.parse(JSON.stringify(defaultInputForm))
};
this.inputParamOpen = true;
},
/**
* 上移功能
* @param {Number} index 当前功能索引
*/
handleInputUp(index) {
if (index === 0) return; // 已经是第一个,不能再上移
try {
// 交换当前项与上一项的位置
const temp = this.form.inputs[index];
this.$set(this.form.inputs, index, this.form.inputs[index - 1]);
this.$set(this.form.inputs, index - 1, temp);
this.$message({
type: 'success',
message: '上移成功!'
});
} catch (error) {
this.$message.error("操作失败:" + error);
}
},
/**
* 下移功能
* @param {Number} index 当前功能索引
*/
handleInputDown(index) {
if (index === this.form.inputs.length - 1) return; // 已经是最后一个,不能再下移
try {
// 交换当前项与下一项的位置
const temp = this.form.inputs[index];
this.$set(this.form.inputs, index, this.form.inputs[index + 1]);
this.$set(this.form.inputs, index + 1, temp);
this.$message({
type: 'success',
message: '下移成功!'
});
} catch (error) {
this.$message.error("操作失败:" + error);
}
},
/**
* 修改输入参数
* @param {Object} row 行数据
* @param {Number} index 行索引
*/
handleInputUpdate(row, index) {
this.inputFormObj = {
isEdit: true,
index: index,
form: JSON.parse(JSON.stringify(row))
};
this.inputParamOpen = true;
},
/**
* 删除输入参数
* @param {Object} row 行数据
* @param {Number} index 行索引
*/
handleInputDelete(row, index) {
this.$confirm("是否确认删除该输入参数?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.form.inputs.splice(index, 1);
this.$message({
type: "success",
message: "删除成功!"
});
})
.catch(() => {
this.$message({
type: "info",
message: "已取消删除"
});
});
},
inputChange() {
this.$forceUpdate();
},
/** 提交验证 */
submitForm: function() {
this.$refs["form"].validate(valid => {
if (valid) {
// 额外校验输入参数
if (!this.form.inputs || this.form.inputs.length === 0) {
this.$message.warning("请至少添加一个输入参数");
return;
}
// 新增和修改操作
if (this.tempType === "add") {
this.$store
.dispatch("AddFunction", this.form)
.then(() => {
this.$message.success("添加成功");
this.$emit("ok");
})
.catch(err => {
this.$message.error("添加失败:" + err);
});
} else if (this.tempType === "update") {
this.$store
.dispatch("EditFunction", {
item: this.form,
idx: this.paramIdx
})
.then(() => {
this.$message.success("修改成功");
this.$emit("ok");
})
.catch(err => {
this.$message.error("修改失败:" + err);
});
}
}
});
},
// 添加一个监听输入参数弹窗关闭的方法
handleInputDialogClose() {
this.$nextTick(() => {
if (this.$refs.inputForm) {
this.$refs.inputForm.clearValidate();
}
});
}
}
};
</script>
<style lang="scss">
.function-form-model {
.enum-box {
border: 1px solid #d8d7d7;
padding: 10px;
margin-bottom: 10px;
.enumTypeDiv {
margin-top: 10px;
}
.enum-header {
margin-bottom: 10px;
}
}
.el-select {
width: 100%;
}
.el-input-number {
width: 100%;
}
.enumTypeDiv {
display: flex;
justify-content: flex-end;
max-height: 200px;
overflow: auto;
.enum-item {
width: 90%;
display: flex;
justify-content: space-around;
align-items: center;
}
}
}
.is-error input {
border-color: #f56c6c;
}
.el-form-item__error {
color: #f56c6c;
font-size: 12px;
line-height: 1;
padding-top: 4px;
position: absolute;
top: 100%;
left: 0;
}
</style>