Vue动态增添表单并赋予增删上下移动等操作
开发需求:前端设计一个表单,依据题目类型,判断是否需要添加内容,若需添加,则可以动态增删、上下移动调整顺序等
开发难点:需根据实际逻辑(如:第一项内容不可删除、上移等),注意按钮的禁用
开发效果:
![image.png](https://pic5.58cdn.com.cn/nowater/webim/big/n_v23173557b7dd040daa66d11c88c75dc9c.png)
![image.png](https://pic5.58cdn.com.cn/nowater/webim/big/n_v2d0b900778fce4f75a7538f24afeb3482.png)
![image.png](https://pic2.58cdn.com.cn/nowater/webim/big/n_v2f5da8f0bd72a418bbdd330e9d04d2f37.png)
![image.png](https://pic1.58cdn.com.cn/nowater/webim/big/n_v27fb806ea32c64f12877b806bcce3c29b.png)
具体实现:
<template>
<div>
<!--新增题目-->
<el-dialog
title="新增题目"
:visible.sync="dialogAddNewQuestion"
customClass="dialogWidth"
center
>
<el-form
ref="addNewForm"
:model="addNewForm"
:rules="addNewQuestionFormRules"
label-width="80px"
:label-position="addNewForm.labelPosition"
>
<el-form-item label="题目序号" prop="sort">
<el-input v-model.number="addNewForm.sort"></el-input>
</el-form-item>
<el-form-item label="题目名称" prop="name">
<el-input v-model="addNewForm.name"></el-input>
</el-form-item>
<el-form-item label="题目类型" prop="type">
<el-select v-model="addNewForm.type" placeholder="请选择题目类型">
<el-option
v-for="item in addNewForm.option"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="题目分数" prop="score">
<el-input v-model.number="addNewForm.score"></el-input>
</el-form-item>
<el-form-item label="题目备注" prop="remark">
<el-input type="textarea" v-model="addNewForm.remark"></el-input>
</el-form-item>
<el-divider></el-divider>
<!--若是单选或多选添加新选项功能-->
<div v-show="addNewForm.type != '问答' && addNewForm.type != '填空'" v-for="(item, index) in addNewForm.options" :key="index">
<el-row :gutter="10">
<el-col :span="4">
<el-form-item label-width="120px" :label="'选项内容' + (index + 1)" :prop="`options.${index}.sort`" :rules="[{ required: true, message: '请输入选项的序号', trigger: 'blur' }, { type: 'number', message: '序号必须为数字值' }]" style="width: 250px">
<el-input v-model.number="item.sort" placeholder="请输入选项排序"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item :prop="`options.${index}.name`" :rules="[{ required: true, message: '请输入选项的内容', trigger: 'blur' }]" style="width: 350px">
<el-input v-model="item.name" placeholder="请输入选项内容"></el-input>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item :prop="`options.${index}.score`" :rules="[{ required: true, message: '请输入选项的分数', trigger: 'blur' }, { type: 'number', message: '分数必须为数字值' }]" style="width: 300px">
<el-input v-model.number="item.score" placeholder="请输入选项分数"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-button
type="danger"
:disabled="index == 0"
@click="deleteItem(item, index)"
>删除</el-button
>
<el-button
icon="el-icon-top"
:disabled="index == 0"
@click="upItem(index)"
circle
></el-button>
<el-button
icon="el-icon-bottom"
:disabled="
index == addNewForm.options.length - 1
"
@click="downItem(index)"
circle
></el-button>
</el-col>
</el-row>
<el-button
icon="el-icon-plus"
v-if="
index + 1 == addNewForm.options.length
"
@click="addItem()"
></el-button>
</div>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button
style="position: absolute; right: 100px; bottom: 10px"
@click="dialogAddNewQuestion = false"
>关闭</el-button
>
<el-button
type="primary"
style="position: absolute; right: 10px; bottom: 10px"
@click="submitNewQuestion"
>新增</el-button
>
</div>
</el-dialog>
</div>
</template>
<script>
import {
createQuestion,
} from "@/api/questionnaire";
export default {
data() {
return {
// 弹窗
dialogAddNewQuestion: false,
// 新增题目表格
addNewForm: {
labelPosition: "left",
// 上一页问卷的id
questionnaireId: this.$route.query.questionnaireId,
sort: null,
name: "",
score: null,
// 默认
type: "填空",
option: [
{ value: "填空", label: "填空" },
{ value: "单选", label: "单选" },
{ value: "多选", label: "多选" },
{ value: "问答", label: "问答" },
],
remark: "",
// 新增题目的新增选项表格
options: [
{
name: "",
score: null,
sort: null,
}
]
},
// 新增题目表格校验
addNewQuestionFormRules: {
sort: [
{ required: true, message: "请输入题目的序号", trigger: "blur" },
{ type: "number", message: "序号必须为数字值" },
],
name: [
{ required: true, message: "请输入题目的名称", trigger: "blur" },
],
score: [
{ required: true, message: "请输入题目的分数", trigger: "blur" },
{ type: "number", message: "分数必须为数字值" },
],
type: [
{ required: true, message: "请选择题目的类型", trigger: "blur" },
]
},
};
},
methods: {
// 新增问卷
addNewQuestion() {
this.dialogAddNewQuestion = true;
},
// 提交新增题目
submitNewQuestion() {
this.$refs["addNewForm"].validate((valid) => {
if (valid) {
createQuestion(this.addNewForm).then(() => {
this.dialogAddNewQuestion = false;
this.fetchQuestionRecord();
this.$notify({
title: "成功",
message: "新增题目成功",
type: "success",
duration: 2000,
});
});
}
});
},
// 新增添加选项内容
addItem() {
this.addNewForm.options.push({
name: "",
score: null,
sort: null,
});
},
// 新增删除选项内容
deleteItem(item, index) {
this.addNewForm.options.splice(index, 1);
this.$message({
message: "删除成功哟~",
type: "success",
});
},
// 新增上移动选项操作
upItem(index) {
let arr = this.addNewForm.options;
arr.splice(index - 1, 1, ...arr.splice(index, 1, arr[index - 1]));
},
// 新增下移选项操作
downItem(index) {
let arr = this.addNewForm.options;
arr.splice(index, 1, ...arr.splice(index + 1, 1, arr[index]));
},
},
};
</script>
<style>
.dialogWidth {
width: 85%;
}
</style>