elementui步骤条页面开发案例
<template>
<div id="bdy">
<div class="tbody">
<el-steps :active="active" finish-status="success">
<el-step title="创建项目"></el-step>
<el-step title="区域基地"></el-step>
<el-step title="实验对象"></el-step>
<el-step title="阶段周期"></el-step>
<el-step title="属性"></el-step>
</el-steps>
<!-- 1创建项目 -->
<el-form :model="form" :rules="projectRules" ref="form" label-width="100px" width="80px" style="margin-top: 30px;">
<div class="el-card" v-if="active==1" style="padding: 20px;">
<el-row>
<el-col :span="12">
<el-form-item label="项目名称:" prop="pName">
<el-input v-model="form.pName" suffix-icon="el-icon-warning-outline" placeholder="请输入实验名"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="运行状态:" prop="baseId">
<treeselect
v-model="form.baseId"
:options="baseOptions"
:normalizer="normalizer"
:show-count="true"
placeholder="请选择区域名称(请勿选择主类目)"
@select="handleSelect"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="项目周期(年):" prop="cycle">
<el-input-number v-model="form.cycle" :min="1" :max="10" style="width: 100%;" placeholder="默认项目周期是1年"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="实验对象:" prop="varietiesId">
<el-select v-model="form.varietiesId" placeholder="请选择实验对象" filterable style="width: 100%">
<el-option
v-for="item in varietiesOptions"
:key="item.varietiesId"
:value="item.varietiesId"
:label="item.varietiesName">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="开始日期:" prop="startDate">
<el-date-picker v-model="form.startDate" type="date" placeholder="选择项目开始日期" style="width: 100%"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="结束日期:" prop="startDate">
<el-date-picker v-model="form.endDate" type="date" placeholder="选择项目结束日期" style="width: 100%"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="负责人:" prop="principalId">
<el-select v-model="form.principalId" placeholder="请选择负责人" filterable style="width:100%">
<el-option
v-for="item in userOptions"
:key="item.principalId"
:value="item.principalId"
:label="item.principalName">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态:" prop="state">
<el-select v-model="form.state" placeholder="请选择状态" style="width: 100%">
<el-option
v-for="(dict,index) in dict.type.dict_onoff_type"
:key="index"
:label="dict.label"
:value="dict.value"
value-key="index">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="项目简介:" prop="description">
<el-input v-model="form.description" type="textarea" suffix-icon="el-icon-warning-outline" :rows="5" maxlength="150" show-word-limit></el-input>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
<!-- 2实验基地 -->
<el-form :model="form2" :rules="projectRules" ref="form2" label-width="100px" width="80px" style="margin-top: 30px">
<div class="el-card" v-if="active==2" style="padding: 20px;">
<el-row>
<el-col :span="12">
<el-form-item label="实验名称:" prop="pName">
<el-input v-model="form.pName" suffix-icon="el-icon-warning-outline" placeholder="请输入实验名"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="区域名称:" prop="baseId">
<treeselect
v-model="form.baseId"
:options="baseOptions"
:normalizer="normalizer"
:show-count="true"
placeholder="请选择区域名称(请勿选择主类目)"
@select="handleSelect"
/>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
<!-- 3实验对象 -->
<el-form :model="form3" :rules="projectRules" ref="form3" label-width="100px" width="80px" style="margin-top: 30px">
<div class="el-card" v-if="active==3" style="padding: 20px;">
<el-tag
:key="tag"
v-for="tag in dynamicObjectTags"
closable
:disable-transitions="false"
@close="handleClose(tag)">
{{tag}}
</el-tag>
<el-input
class="input-new-tag"
v-if="inputVisible"
v-model="inputValue"
ref="saveTagInput"
size="small"
@keyup.enter.native="handleInputConfirm"
@blur="handleInputConfirm"
>
</el-input>
<el-button v-else class="button-new-tag" size="small" @click="showInput">+ 新增实验对象</el-button>
</div>
</el-form>
<!-- 4阶段周期 -->
<el-form :model="form4" :rules="projectRules" ref="form4" label-width="100px" width="80px" style="margin-top: 30px">
<div class="el-card" v-if="active==4" style="padding: 20px;">
<el-tag
:key="tag"
v-for="tag in dynamicStageTags"
closable
:disable-transitions="false"
@close="handleClose(tag)">
{{tag}}
</el-tag>
<el-input
class="input-new-tag"
v-if="inputVisible"
v-model="inputValue"
ref="saveTagInput"
size="small"
@keyup.enter.native="handleInputConfirm"
@blur="handleInputConfirm"
>
</el-input>
<el-button v-else class="button-new-tag" size="small" @click="showInput">+ 新增阶段周期</el-button>
</div>
</el-form>
<!-- 5添加记录 -->
<el-form :model="form5" :rules="projectRules" ref="form5" label-width="100px" width="80px" style="margin-top: 30px">
<div class="info" v-if="active==5">
<div class="box-card" shadow="hover">
<el-card class="box-card" v-for="(item,index) in recordData" :key="index" v-if="item.formShow">
<div slot="header" class="clearfix">
<span>{{item.formName}}</span>
<el-button style="float: right; padding: 3px 0;color:#f56c68;" type="text" @click="taskDelHandle(index)">删除
</el-button>
</div>
<el-form :ref="item.formRef" :key="item.index" label-width="140px" enctype="multipart/form-data">
<template v-for="(propertys,index2) in (item.formModel)">
<el-form-item :label="propertys.propertyName" :prop="propertys.propertyAlias" :key="index2">
<el-input style="width:80%" v-model="propertys.propertyValue" size="small"></el-input>
<i v-if="propertys.fix" style="padding:0 7px;">
<el-button type="danger" @click="remoteItem(index,index2)" size="small" class="el-icon-delete">删除</el-button>
</i>
</el-form-item>
<div v-if="index2 == item.formModel.length-1" style="text-align: center">
<el-button type="warning" @click="addCustomAttr(index)" size="small" class="el-icon-user">自定义</el-button>
</div>
</template>
<!-- 上传图片/视频-->
<el-form-item label="任务图片/视频">
<el-upload
class="upload-demo"
ref="upload"
:action="upload.url"
:headers="upload.headers"
:on-preview="handlePreview"
:on-success="handleSuccess"
:on-error="handleError"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:on-change="handleChange"
:limit="3"
:on-exceed="handleExceed"
:file-list="item.fileList"
:disabled="upload.isUploading"
accept=".jpg,.jpeg,.png,.gif,.bmp,.JPG,.JPEG,.PBG,.GIF,.BMP"
list-type="picture">
<el-button size="small" type="primary">点击上传</el-button>
<span slot="tip" class="el-upload__tip"> 只能上传jpg/png文件,且不超过500kb</span>
</el-upload>
</el-form-item>
</el-form>
</el-card>
</div>
<div class="bottom-divider">
<span class="divider-btn">
<el-button type="success" size="small" icon="el-icon-circle-plus-outline" @click="taskAddHandle()">添加新记录</el-button>
</span>
</div>
</div>
</el-form>
<div style="text-align: center">
<el-button style="margin-top: 12px;" @click="pre" v-if="active>1" type="primary">上一步</el-button>
<el-button style="margin-top: 12px;" @click="next" v-if="active<5" type="success">下一步</el-button>
<el-button style="margin-top: 12px;" @click="onSubmit" v-if="active===5" type="success" >提交</el-button>
</div>
</div>
<!--新增自定义填写属性窗口-->
<el-dialog title="新增自定义填写属性" :visible.sync="dialogVisible" width="500px" :before-close="diyhandleClose">
<el-form ref="form" :model="customForm" label-width="140px" style="width: 500px">
<el-row>
<el-col :span="12">
<el-form-item label="自定义属性名">
<el-autocomplete class="inline-input"
size="small"
v-model="customForm.dynamicName"
:fetch-suggestions="querySearch"
@select="handleSelect"
style="width: 100%">
</el-autocomplete>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="自定义属性类型">
<el-select v-model="customForm.dynamicType" size="small" placeholder="请选择" style="width: 100%">
<el-option
v-for="(item,index) in dynamicOption"
:key="item.propertyType"
:label="item.label"
:value="item.propertyType">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="addDynamicProperty()">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
//表单js代码
import Qs from "qs";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import {getToken} from "@/utils/auth";
import {getStageProperty, addTask} from "@/api/projectmgr/task";
export default {
dicts: ['dict_onoff_type'],
components: {Treeselect},//树组件
data() {
return {
dynamicObjectTags: ['玉米', '向日葵', '黄豆'],
dynamicStageTags: ['发芽期', '幼苗期', '选种期', '播种期', '现蕾期', '开花期', '成熟期'],
inputVisible: false,
inputValue: '',
active: 1,
stateOptions: [],
varietiesOptions: [],
groupOptions: [],
areaOptions: [],
ids: [], // 选中数组
userOptions: [],//负责人下拉列表
baseOptions: [], // 基地树选项
isExpandAll: false, // 是否展开,默认全部折叠
refreshTable: true, // 重新渲染表格状态
showSearch: true, // 显示搜索条件
loading: true, // 遮罩层
open: false,// 是否显示弹出层
queryParams: { // 查询参数
pageNum: 1,
pageSize: 10,
pName: null,
state: null,
},
form: {
area: ['个人成长'],
checkAll: false,
cities: cityOptions,
isIndeterminate: true,
quality: 0,
imageUrl: '',
username: '',
tell: '',
indentity: '',
number: '',
instroduce: '',
time: ''
},
form2: {
area: ['个人成长'],
checkAll: false,
cities: cityOptions,
isIndeterminate: true,
quality: 0,
imageUrl: '',
username: '',
tell: '',
indentity: '',
number: '',
instroduce: '',
time: ''
},
form3: {
area: ['个人成长'],
checkAll: false,
cities: cityOptions,
isIndeterminate: true,
quality: 0,
imageUrl: '',
username: '',
tell: '',
indentity: '',
number: '',
instroduce: '',
time: ''
},
form4: {},
form5: {},
form6: {},
projectRules: {
pName: [
{required: true, message: '请输入项目名称', trigger: 'blur'},
{min: 1, max: 10, message: '长度在 1 到 10 个字符', trigger: 'blur'}
],
varietiesId: [
{required: true, message: '请选择实验对象', trigger: 'change'}
],
description: [
{required: true, message: '请填写项目简介', trigger: 'blur'}
],
baseId: [
{required: true, message: '请选择实验基地', trigger: 'change'}
],
area: [
{required: true, message: '请选择项目具体区域', trigger: 'change'}
],
principalId: [
{required: true, message: '请选择负责人', trigger: 'change'}
]
},
recordData: [{
formModel: [],//表单model
formRef: 'recordForm',//表单ref
formShow: true,//表单是否显示的控制
formName: '记录1',//表单标题
fileList: [],
}],
url: process.env.VUE_APP_BASE_API + "/task/upload",
minioUrl: process.env.VUE_APP_MINIO,
// 用户导入参数
upload: {
// 是否显示弹出层(用户导入)
open: false,
// 弹出层标题(用户导入)
title: "",
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的用户数据
updateSupport: 0,
// 设置上传的请求头部
headers: {Authorization: "Bearer " + getToken()},
// 上传的地址
url: process.env.VUE_APP_BASE_API + "/task/upload", // 上传的图片服务器地址
minioUrl: process.env.VUE_APP_MINIO // 显示的图片服务器地址
},
dialogVisible: false,
queryParams: {},
customForm: {
dynamicName: '',
dynamicType: '',
},
dynamicOption: [
{
propertyType: 'datetime',
label: '时间'
}, {
propertyType: 'varchar',
label: '文字'
}
],
TaskForm: { // 表详细信息
pId: '',
pName: '',
baseParentId: '',
baseParentName: '',
baseId: '',
baseName: '',
varietiesId: '',
varietiesName: '',
stageId: '',
growthStageId: '2',
stateName: '',
cycle: '',
taskId: '',
},
formIndex: 2,//添加记录从2开始
customFormIndex: 0,
attrLen: 0,
}
},
mounted() {
let item = {growthStageId: 2}
this.stagePropertyList(item)
},
methods: {
/** 提交保存*/
onSubmit() {
this.$confirm('此操作将保存记录, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//this.form.checkedCities获取多选框的内容 zxs[this.form.radio] this.form.imageUrl
//开始提交 在这里进行跨域请求
this.axios({
method: "post",
url: "/api/PsychoSys/tuser.action",
data: Qs.stringify(this.form)
}).then(res => {
this.$router.push("/tinfo");
}).catch(function (err) {
console.log(err);
});
/*在这里进行跨域请求*/
//开始提交
}).catch(() => {
this.$message({type: 'info', message: '已取消修改'});
});
},
handleAvatarSuccess(res, file) {
this.form.imageUrl = URL.createObjectURL(file.raw);
},
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg';
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!');
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!');
}
return isJPG && isLt2M;
},
handleCheckAllChange(val) {
this.form.area = val ? cityOptions : [];
this.isIndeterminate = false;
},
handleCheckedCitiesChange(value) {
let checkedCount = value.length;
this.checkAll = checkedCount === this.form.cities.length;
this.isIndeterminate = checkedCount > 0 && checkedCount < this.form.cities.length;
}, next() {
if (this.active++ > 5) this.active = 1;
},
pre() {
if (this.active-- < 2) this.active = 1;
},
/** 基地树点击点击事件**/
handleSelect(row) {
this.projectForm.baseParentId = row.parentId;
},
/** 转换部门数据结构 */
normalizer(node) {
if (node.children && !node.children.length) {
delete node.children;
}
return {
id: node.baseId,
label: node.baseName,
children: node.children
};
},
/** 文件列表移除文件时的钩子*/
handleRemove(file, fileList) {
console.log(file, fileList);
},
/** 点击文件列表中已上传的文件时的钩子*/
handlePreview(file) {
console.log(file);
},
handleChange(file, fileList) {
if (fileList.length > 1) {
fileList.shift()
}
},
handleSuccess(response, file, fileList) {
this.upload.open = false;
this.upload.isUploading = false;
this.recordData[0].fileList.push({name: response.newFileName, url: this.upload.minioUrl + response.url});
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", {dangerouslyUseHTMLString: true});
},
handleError() {
this.$message.error("图片插入失败");
},
/** 文件超出个数限制时的钩子*/
handleExceed(files, fileList) {
this.$message.warning(`当前限制选择 2 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
},
/** 删除文件之前的钩子*/
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}?`);
},
handleClose(tag) {
this.dynamicTags.splice(this.dynamicTags.indexOf(tag), 1);
},
showInput() {
this.inputVisible = true;
this.$nextTick(_ => {
this.$refs.saveTagInput.$refs.input.focus();
});
},
handleInputConfirm() {
let inputValue = this.inputValue;
if (inputValue) {
this.dynamicTags.push(inputValue);
}
this.inputVisible = false;
this.inputValue = '';
},
/** 查询通用属性列表*/
stagePropertyList(item) {
if (item) {
this.queryParams.growthStageId = item.growthStageId;
getStageProperty(this.queryParams).then(res => {
if (res.code == 200) {
this.$set(this.recordData[0], "formModel", res.data);
this.attrLen = res.data.length
}
});
}
},
/** 自定义属性*/
addCustomAttr(i) {
this.customFormIndex = i
this.dialogVisible = true;
},
/** 查询按钮*/
querySearch(queryString, cb) {
let stateList = this.stateList;
//let results = queryString ? stateList.filter(this.createFilter(queryString)) : stateList;
//cb(results);
},
/** 确认关闭按钮*/
diyhandleClose(done) {
this.$confirm('确认关闭?').then(_ => {
done();
}).catch(_ => {
});
},
/** 添加自定义属性*/
addDynamicProperty() {
let i = this.recordData[this.customFormIndex].formModel.length - this.attrLen
let obj = {
propertyName: this.customForm.dynamicName,
propertyType: this.customForm.dynamicType,
property: 'dynamic' + i,//属性英文名称
propertyAlias: 'dynamic' + i,//属性中文名称
vId: 1,
fix: true,
propertyCategory: 'custom'
}
this.recordData[this.customFormIndex].formModel.push(obj);
this.dialogVisible = false
},
/** 添加新记录*/
taskAddHandle() {
if (this.recordData.length == 0) {
this.formIndex = 1;
}
let newRecord = {
formModel: [],//表单model
formRef: 'recordForm' + this.formIndex,//表单ref
formShow: true,//表单是否显示的控制
formName: '记录' + this.formIndex//表单标题
}
let item = {growthStageId: parseInt(this.TaskForm.growthStageId)};
getStageProperty(item).then(res => {
if (res.code == 200) {
this.$set(newRecord, "formModel", res.data);
this.recordData.push(newRecord);
this.attrLen = res.data.length
}
});
this.formIndex++;
},
},
}
//表单js代码
</script>
<style>
.tbody {
width: 80%;
margin-left: 10%;
margin-top: 1%;
}
/* 表单 */
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
.el-tag + .el-tag {
margin-left: 10px;
}
.button-new-tag {
margin-left: 10px;
height: 32px;
line-height: 30px;
padding-top: 0;
padding-bottom: 0;
}
.input-new-tag {
width: 90px;
margin-left: 10px;
vertical-align: bottom;
}
</style>
显示效果:
总结:
5个步骤页面各自放到5个不同的form表单,最后提交到后台.向导式步骤页面在elementui官网里查API就知道了,本人代码运行您电脑上很可能报错的情况,因为有些是调后台接口。
本文来自博客园,作者:星星之草%,转载请注明原文链接:https://www.cnblogs.com/zhaodefu/p/16611862.html