,from表单
有两个parmas,展示的数据,rules,校验规则
看代码,虽然没用
1,如果弹窗后关闭弹窗,再打开发现有校验问题,这个需要重置表单,使用resetfields() 方法,这个方法可以对整个表单进行重置,将所有字段值重置为初始值并移除校验结果;
坑:也会清除并初始化所有的默认数据,所以要注意使用
2,如果再点击弹窗,弹窗中有类似于切换的页面的,如
![](https://img-blog.csdnimg.cn/img_convert/ddde02ef2f76f76795290096eaea45cd.png)
弹出后后面需要往弹窗传数据,并且点击对应的编辑弹出对应的导航数据时,要在关闭弹窗的时候将导航脚标设置为初始值;
export const BASE_FORM = [
{
label: '单号',
key: 'superviseNo',
type: 'input',
disabled: true,
loading: false,
optionList: [],
class: '',
xl: 6,
lg: 8,
md: 12,
sm: 12,
},
{
label: '事项',
key: 'superviseDesc',
type: 'input',
maxLength: 50,
loading: false,
optionList: [],
class: '',
xl: 6,
lg: 8,
md: 12,
sm: 12,
},
{
label: '部门',
key: 'creatorId',
labelKey: 'creatorName',
addKey: {
label: {
getLable: 'deptName',
subLable: 'deptName',
},
value: {
getLable: 'deptId',
subLable: 'deptId',
},
}, // 附带值,下拉选之后,其他内容默认展示
type: 'selectRemote',
apiUrl: 'getStaffList',
isFilterable: true,
isRemote: true,
loading: false,
disabled: true,
optionList: [],
class: 'hasAddKey',
xl: 6,
lg: 8,
md: 12,
sm: 12,
},
{
label: '日期',
key: 'createTime',
type: 'input',
disabled: true,
loading: false,
optionList: [],
class: '',
xl: 6,
lg: 8,
md: 12,
sm: 12,
},
{
label: '联系电话',
key: 'contactNumber',
type: 'input',
disabled: true,
loading: false,
optionList: [],
class: '',
xl: 6,
lg: 8,
md: 12,
sm: 12,
},
{
label: '类别',
key: 'superviseCategory',
labelKey: 'superviseCategoryName',
type: 'select',
optionList: [],
class: '',
xl: 6,
lg: 8,
md: 12,
sm: 12,
},
{
label: '来源',
key: 'superviseSource',
labelKey: 'superviseSourceName',
type: 'select',
optionList: [],
class: '',
xl: 6,
lg: 8,
md: 12,
sm: 12,
},
{
label: '签发人',
key: 'signerId',
labelKey: 'signerName', // 需要给后台同时传label 和 value 2个值
type: 'selectRemote',
apiUrl: 'getUserLeader',
defaultValue: 'gyh',
defaultLabelValue: '',
isFilterable: true,
isRemote: true,
loading: false,
optionList: [{
deptId: '2',
deptName: '公司领导',
loginId: '',
userName: '',
workCode: 'CT00142',
}],
class: '',
xl: 6,
lg: 8,
md: 12,
sm: 12,
},
{
label: '反馈周期',
key: 'feedbackPeriod',
defaultValue: 'week',
type: 'select',
loading: false,
optionList: [],
class: '',
xl: 6,
lg: 8,
md: 12,
sm: 12,
},
{
label: '计划办结时限',
key: 'planFinishDate',
type: 'date',
optionList: [],
class: '',
xl: 6,
lg: 8,
md: 12,
sm: 12,
},
{
label: '要求',
key: 'superviseRequirements',
type: 'textarea',
optionList: [],
class: '',
xl: 24,
lg: 24,
md: 24,
sm: 24,
},
{
label: '备注',
key: 'remark',
type: 'textarea',
notRequired: true,
optionList: [],
class: '',
xl: 24,
lg: 24,
md: 24,
sm: 24,
},
{
label: '附件',
key: 'attachmentList',
type: 'uploadFile',
isMultiple: true,
loading: false,
notRequired: true,
optionList: [],
class: '',
xl: 24,
lg: 24,
md: 24,
sm: 24,
},
];
<template>
<el-form
class="supervise-detail__form"
ref="baseForm"
:rules="baseRules"
:model="baseForm"
label-position="top"
>
<el-row :gutter="32">
<el-col
v-for="item in baseFormList"
:key="item.key"
:xl="item.xl"
:lg="item.lg"
:md="item.md"
:sm="item.sm"
>
<el-form-item v-if="!item.notShow" :class="item.class" :prop="item.key">
<template slot="label">
{
{ item.label }}
<!-- 提示 -->
<el-popover
v-if="item.tipsType"
popper-class="supervise-detail__tips"
placement="bottom"
trigger="hover"
>
<div v-if="item.tipsType === 'text'" style="max-width: 600px">
{
{ item.tips }}
</div>
<div v-else-if="item.tipsType === 'table'" style="max-width: 600px">
<el-table
stripe
tooltip-effect="light"
:cell-style="getCellStyle"
:data="baseForm[item.tipsKey]"
style="width: 100%;">
<el-table-column
show-overflow-tooltip
v-for="tableItem in item.tipsHeader"
:key="tableItem.key"
:prop="tableItem.key"
:label="tableItem.label"
:width="tableItem.width || 'auto'"
:align="tableItem.algin || 'left'"
>
<template slot-scope="scope">
{
{ scope.row[tableItem.key] }}
</template>
</el-table-column>
</el-table>
</div>
<svg-icon
style="margin-left: 5px;"
slot="reference"
class="icon"
icon-class="infoTips"
/>
</el-popover>
</template>
<!-- 输入框 -->
<el-input
:disabled="item.disabled ? true : false"
v-emoji
:maxlength="item.maxLength || 500"
v-if="item.type === 'input'"
v-model.trim="baseForm[item.key]"
:placeholder="`请输入${item.label}`"
>
</el-input>
<!-- 下拉选 -->
<el-select
:disabled="item.disabled ? true : false"
v-else-if="item.type === 'select'"
v-model="baseForm[item.key]"
:filterable="item.isFilterable"
:multiple="item.isMultiple"
:placeholder="`请选择${item.label}`"
collapse-tags
@change="(val) => changeSelect(val, item, baseForm)"
>
<el-option
v-for="optionItem in item.optionList"
:key="optionItem.value"
:label="optionItem.label"
:value="optionItem.value"
></el-option>
</el-select>
<!-- 远程选择(员工) -->
<el-select
:disabled="item.disabled ? true : false"
v-else-if="item.type === 'selectRemote'"
v-model="baseForm[item.key]"
:filterable="item.isFilterable"
:remote="item.isRemote"
:multiple="item.isMultiple"
:placeholder="`请输入${item.label}`"
:remote-method="(query) => getRemoteOption(query, item)"
:loading="item.loading"
@focus="getRemoteOption('', item)"
@change="(str) => changeUserSelect(str, item, baseForm)"
>
<div slot="prefix">
<i class="el-icon-search"></i>
</div>
<el-option
v-for="optionItem in item.optionList"
:key="optionItem.loginId"
:label="optionItem.userName"
:value="optionItem.loginId"
>
{
{ `${optionItem.userName} - ${optionItem.workCode}` }}
</el-option>
</el-select>
<el-input
v-emoji
disabled
class="addKey"
:maxlength="item.maxLength || 500"
v-if="item.addKey"
v-model.trim="baseForm[item.addKey.label.subLable]"
>
</el-input>
<!-- 时间选择 -->
<el-date-picker
:disabled="item.disabled ? true : false"
v-else-if="item.type === 'date'"
v-model="baseForm[item.key]"
type="date"
:editable="false"
:clearable="false"
value-format="yyyy-MM-dd"
:placeholder="`请选择${item.label}`"
>
</el-date-picker>
<!-- 级联 -->
<el-cascader
:disabled="item.disabled ? true : false"
v-else-if="item.type === 'cascader'"
:props="{
checkStrictly: item.isCheckStrictly,
multiple: item.isMultiple,
}"
collapse-tags
v-model="baseForm[item.key]"
:options="item.optionList"
@change="(val) => changeDepSelect(val, item, baseForm)"
:placeholder="`请选择${item.label}`"
>
</el-cascader>
<!-- 文本域 -->
<el-input
:disabled="item.disabled ? true : false"
:maxlength="item.maxLength || 500"
show-word-limit
v-emoji
v-else-if="item.type === 'textarea'"
type="textarea"
:rows="2"
:autosize="{
minRows: 3,
}"
v-model.trim="baseForm[item.key]"
:placeholder="`请输入${item.label}`"
>
</el-input>
<!-- 附件上传 -->
<el-upload
:class="{hideBtn: item.hideBtn}"
v-else-if="item.type === 'uploadFile'"
class="upload"
accept="*"
:disabled="item.disabled || uploading"
:action="uploadUrl"
:file-list="baseForm[item.key]"
:before-upload="fileBeforeUpload"
:on-preview="downloadFile"
:on-error="uploadError"
:on-progress="uploadProgress"
:on-remove="(file)=>fileRemove(file, item)"
:on-success="(res) => uploadSuccess(res, item)"
>
<el-button type="primary" :disabled="uploading">
上传附件
</el-button>
<div slot="tip" class="el-upload__tip">
仅支持上传以下类型文件: .pdf,.xls,.xlsx,.doc,.docx,.zip,.png,.jpg,.jpeg,.rar,且单个文件不超过50MB
</div>
</el-upload>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
// import { api } from '@/api';
import { flat } from '@/util/validate';
import myForm from '@/mixins/my-form';
export default {
name: 'my-form',
mixins: [myForm],
components: {},
props: {
// 输入框类型
baseFormList: {
type: Array,
default: () => [],
},
// 输入框选中后的传参
baseForm: {
type: Object,
default: () => {},
},
},
watch: {
baseForm: {
handler(val) {
console.log('查看baseForm', val);
if (val) {
this.updateForm();
}
},
deep: true,
},
baseFormList: {
handler(val) {
console.log('myfrom的表单数据baseFormList', val);
},
deep: true,
},
},
data() {
return {
// 督办立项单
baseRules: {},
// 扁平化部门
depOptions: [],
// 附件上传地址
uploadUrl: `${process.env.VUE_APP_BASE_URL}common/file/upload`,
uploading: false,
};
},
created() {
this.initData();
this.initOption();
},
methods: {
...mapActions(['apiGetDepList']),
// 更新数据
updateForm() {
// 关闭数据后更新依然要刷新下拉框
this.initOption();
this.$emit('update:baseForm', this.baseForm);
},
// 取消校验
closeBaseForm() {
this.$refs.baseForm.resetFields();
},
// 校验必填项
checkValidate() {
const that = this;
console.log(this.baseFormList, this.baseForm);
return new Promise((resolve) => {
this.$refs.baseForm.validate((valid) => {
if (!valid) {
resolve(false);
return false;
}
that.updateForm();
resolve(true);
return true;
});
});
},
// 重置数据
resetForm() {
this.$refs.baseForm.resetFields();
},
/**
* 附件相关
*/
// 上传校验
fileBeforeUpload(file) {
const isLt50M = file.size / 1024 / 1024 < 50;
if (!isLt50M) {
this.$message.error('上传文件大小不能超过 50MB!');
return false;
}
const suffix = file.name.split('.').slice(-1)[0].toLowerCase();
const types = ['pdf', 'xls', 'xlsx', 'doc', 'docx', 'zip', 'png', 'jpg', 'jpeg', 'rar'];
const isRightType = types.includes(suffix);
if (!isRightType) {
this.$message.error('仅支持上传以下类型文件:.pdf|.xls|.xlsx|.doc|.docx|.zip|.png|.jpg|.jpeg|.rar');
return false;
}
return isLt50M && isRightType;
},
// 移除文件
fileRemove(file, item) {
this.baseForm[item.key] = this.baseForm[item.key].filter(
(el) => (el.url !== file.url),
);
},
// 上传中
uploadProgress() {
this.uploading = true;
},
// 上传失败
uploadError(res) {
this.$message.error(res.message);
},
// 上传成功
uploadSuccess(res, item) {
this.uploading = false;
if (res.messageCode === '200') {
this.baseForm[item.key].push({
name: res.data.docName,
...res.data,
});
this.$message({
message: '上传成功',
type: 'success',
});
} else {
this.$message({
message: res.message,
type: 'error',
});
}
},
// 下载文件
downloadFile(file) {
if (file.url) {
const link = document.createElement('a');
link.style.display = 'none';
link.href = file.location;
link.setAttribute('download', file.name);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
},
// 数据初始化
initData() {
// console.log(this.baseForm, this.baseFormList);
// 督办立项单
this.baseFormList.forEach((el) => {
if (el.isMultiple && !el.labelKey) {
this.$set(this.baseForm, el.key, []);
} else if (!el.isMultiple && el.labelKey) {
this.$set(this.baseForm, el.key, '');
this.$set(this.baseForm, el.labelKey, '');
} else if (!el.isMultiple && !el.labelKey) {
this.$set(this.baseForm, el.key, '');
}
if (el.defaultValue) {
this.$set(this.baseForm, el.key, el.defaultValue);
}
if (el.defaultLabelValue) {
this.$set(this.baseForm, el.labelKey, el.defaultLabelValue);
}
if (el.notRequired) {
return false;
}
const rules = [];
const inputType = ['input', 'textarea'];
if (inputType.indexOf(el.type) > -1) {
rules.push({
required: true,
message: `请输入${el.label}`,
trigger: ['change', 'blur'],
});
this.$set(this.baseRules, el.key, rules);
} else {
rules.push({
required: true,
message: `请选择${el.label}`,
trigger: ['change'],
});
this.$set(this.baseRules, el.key, rules);
}
return true;
});
// console.log(this.baseForm, this.taskInfo, this.baseRules);
},
// 下拉选初始化
async initOption() {
// 部门处理
const res = await this.apiGetDepList();
// 部门扁平化处理,方便获取名称
this.depOptions = flat(res);
// 部门相关下拉选,在这里可以更改下拉框的重置参数
const dep = ['hostUnitId', 'assistanceUnitId', 'hostUnitName', 'assistanceUnitName'];
this.baseFormList.forEach((el) => {
if (this.getConditionObj[el.key]) {
this.$set(el, 'optionList', this.getConditionObj[el.key]);
}
if (dep.indexOf(el.key) > -1) {
this.$set(el, 'optionList', res[0].children);
}
});
},
},
computed: {
...mapGetters(['getConditionObj', 'getUserInfo']),
},
};
</script>