You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

888 lines
29 KiB

<template>
<div class="currenForm">
<!-- @submit.native.prevent 阻止form只有一个input输入框回车触发提交事件 -->
<el-form
ref="form"
:size="size"
:label-position="labelPosition"
:inline="inline"
:label-width="labelWidth"
:rules="rules"
:model="searchData"
@submit.native.prevent
v-if="!hide ? true : false"
>
<el-row :gutter="40">
<el-col
:span="item.colSpan"
v-for="(item, index) in searchForm"
:key="index"
>
<el-form-item
:label="item.label"
:prop="item.showProp ? item.prop + '.' + item.showProp : item.prop"
v-if="!item.hide ? true : false"
>
<!-- 输入框 onkeyup: 正则表达式,用于前端输入校验工作-->
<!-- :onkeyup="item.onkeyup" -->
<el-input
v-if="item.type === 'input'"
v-model="searchData[item.prop]"
:maxlength="item.maxlength"
:onkeyup="itemOnKeyUp(item,searchData[item.prop])"
clearable
:disabled="Boolean(item.disabled)"
:placeholder="item.placeholder || '请输入' + item.label"
:prefix-icon="item.icon"
:show-password="item.showPassword"
@change="changeInput(item.prop,$event)"
@clear="clearInput(item.prop,$event)"
@blur="
inputPlaceholder($event, item, 'blur',searchData)
"
@focus="inputPlaceholder($event, item, 'focus')"
></el-input>
<!-- 输入框(有上下增加按钮框) onkeyup: 正则表达式,用于前端输入校验工作-->
<el-input-number
v-if="item.type === 'number'"
v-model="searchData[item.prop]"
:onkeyup="item.onkeyup"
:disabled="Boolean(item.disabled)"
@change="changeInput(item.prop,$event)"
@clear="clearInput(item.prop,$event)"
:min="item.min"
:max="item.max"
:precision="item.precision"
class="inputNameberClass"
@blur="
inputPlaceholder($event, item, 'blur',searchData)
"
@focus="inputPlaceholder($event, item, 'focus')"
></el-input-number>
<!-- 输入框(只能输入数字) onkeyup: 正则表达式,用于前端输入校验工作-->
<!-- oninput="value=value.replace(/[^\d]/g,'')" -->
<el-input
v-if="item.type === 'inputNumber'"
v-model="searchData[item.prop]"
:maxlength="item.maxlength"
:onkeyup="typeNumberOnkeyup(item,searchData[item.prop])"
clearable
:disabled="Boolean(item.disabled)"
:placeholder="item.placeholder || '请输入' + item.label"
:prefix-icon="item.icon"
:show-password="item.showPassword"
@change="changeInput(item.prop,$event)"
@clear="clearInput(item.prop,$event)"
@blur="
inputPlaceholder($event, item, 'blur',searchData)
"
@focus="inputPlaceholder($event, item, 'focus')"
></el-input>
<!-- 对象输入框 -->
<el-input
v-if="item.type === 'objectInput'"
v-model="searchData[item.prop][item.showProp]"
:maxlength="item.maxlength"
clearable
:disabled="Boolean(item.disabled)"
:placeholder="item.placeholder || '请输入' + item.label"
:prefix-icon="item.icon"
:show-password="item.showPassword"
@blur="
inputPlaceholder($event, item, 'blur',searchData)
"
@focus="inputPlaceholder($event, item, 'focus')"
></el-input>
<!-- 对象富文本框 -->
<el-input
v-if="item.type === 'objectTextarea'"
type="textarea"
v-model="searchData[item.prop][item.showProp]"
:placeholder="item.placeholder || '请输入' + item.label"
></el-input>
<!--查询下拉-->
<el-autocomplete
v-if="item.type === 'autocomplete'"
class="inline-input"
style="width: 100%"
v-model="searchData[item.prop]"
:disabled="Boolean(item.disabled)"
:fetch-suggestions="
(queryString, cb) => {
querySearch(queryString, cb, item);
}
"
:placeholder="item.placeholder || '请输入' + item.label"
@select="handleSelect($event, item)"
>
<el-button
slot="append"
icon="el-icon-search"
v-if="item.click"
@click="item.click(item)"
style="color: #1890ff; background-color: #ffffff"
></el-button>
</el-autocomplete>
<!--对象查询下拉-->
<el-autocomplete
v-if="item.type === 'objectAutocomplete'"
class="inline-input"
style="width: 100%"
v-model="searchData[item.prop][item.showProp]"
:fetch-suggestions="
(queryString, cb) => {
querySearch(queryString, cb, item);
}
"
:placeholder="item.placeholder || '请输入' + item.label"
@select="handleSelect($event, item)"
>
<el-button
slot="append"
icon="el-icon-search"
v-if="item.click"
@click="item.click(item)"
style="color: #1890ff; background-color: #ffffff"
></el-button>
</el-autocomplete>
<!-- 文本框 -->
<el-input
v-if="item.type === 'textarea'"
:type="item.type"
v-model="searchData[item.prop]"
:rows="item.rows"
:placeholder="item.placeholder || '请输入' + item.label"
:maxlength="item.maxlength"
show-word-limit
></el-input>
<!-- 下拉框 -->
<el-select
v-if="item.type === 'select'"
v-model="searchData[item.prop]"
:loading="selectLoading"
:clearable="item.clearable"
:multiple="item.multiple"
:disabled="Boolean(item.disabled)"
:filterable="item.filterable"
:allow-create="item.allowCreate"
style="width: 100%"
:placeholder="item.placeholder || '请输入' + item.label"
@change="changeSelect(item.prop,$event)"
>
<el-option
v-for="(op, index) in selectOptions(item.options) ||
item.userOptions"
:label="op[item.optionsLabel] || op.label"
:value="op[item.optionsValue] || op.value"
:key="index"
></el-option>
</el-select>
<!-- 链接接口filter下拉框 -->
<filterSelect
v-if="item.type === 'filterSelect'"
:selectModel="searchData[item.prop]"
:selectItem="item"
@filterOptionSelectHandle="filterOptionSelectHandle"
@filterClearHandle="filterClearHandle(item)"
></filterSelect>
<!--对象下拉框 -->
<el-select
v-if="item.type === 'objectSelect'"
v-model="searchData[item.prop][item.showProp]"
:loading="selectLoading"
:clearable="item.clearable"
:multiple="item.multiple"
:disabled="Boolean(item.disabled)"
:filterable="item.filterable"
:allow-create="item.allowCreate"
style="width: 100%"
:placeholder="item.placeholder || '请输入' + item.label"
>
<el-option
v-for="(op, index) in selectOptions(item.options) ||
searchOptions['options']"
:label="op[item.optionsLabel] || op.label"
:value="op[item.optionsValue] || op.value"
:key="index"
></el-option>
</el-select>
<!-- 下拉框多选 -->
<el-select
v-if="item.type === 'selectArray'"
v-model="searchData[item.prop]"
multiple
:placeholder="item.placeholder || '请选择' + item.label"
style="width: 100%"
>
<el-option
v-for="(op, index) in selectOptions(item.options) ||
item.searchOptions"
:label="op[item.optionsLabel] || op.label"
:value="op[item.optionsValue] || op.value"
:key="index"
></el-option>
</el-select>
<!-- 单选 -->
<el-radio-group
v-if="item.type === 'radio'"
v-model="searchData[item.prop]"
:disabled="Boolean(item.disabled)"
@change="radioChange(item.prop,$event)"
>
<el-radio
v-for="ra in searchOptions[item.radio]"
:label="ra.id"
:key="ra.value"
>{{ ra.label }}</el-radio
>
</el-radio-group>
<!-- 单选按钮 -->
<el-radio-group
v-if="item.type === 'radioButton'"
v-model="searchData[item.prop]"
@change="item.change && item.change(searchData[item.prop])"
>
<el-radio-button
v-for="ra in searchOptions[item.radios]"
:label="ra.value"
:key="ra.value"
>{{ ra.label }}</el-radio-button
>
</el-radio-group>
<!-- 复选框 -->
<el-checkbox v-if="item.type === 'checkbox'" :indeterminate="indeterminate" v-model="item.checkAll" @change="handleCheckAllChange($event,item)">全选</el-checkbox>
<el-checkbox-group
v-if="item.type === 'checkbox'"
v-model="searchData[item.prop]"
@change="handleCheckedCitiesChange($event,item)"
>
<el-checkbox
v-for="ch in searchOptions[item.checkboxs]"
:label="ch"
:key="ch"
>{{ ch }}</el-checkbox
>
</el-checkbox-group>
<!-- 日期 -->
<el-date-picker
v-if="item.type === 'date'"
v-model="searchData[item.prop]"
style="width: 100%"
:disabled="Boolean(item.disabled)"
:placeholder="item.placeholder || '选择日期'"
value-format="yyyy-MM-dd"
></el-date-picker>
<!-- 时间 -->
<el-time-picker
v-if="item.type === 'time'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder || '选择时间'"
style="width: 100%"
:picker-options="{
selectableRange: '00:00:00 - 23:59:00',
}"
:disabled="Boolean(item.disabled)"
format="HH:mm"
value-format="yyyy-MM-ddTHH:mm:ss"
></el-time-picker>
<!-- 日期时间 -->
<el-date-picker
v-if="item.type === 'dateTime'"
type="datetime"
v-model="searchData[item.prop]"
:placeholder="item.placeholder || '选择日期时间'"
style="width: 100%"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-ddTHH:mm:ss"
:disabled="Boolean(item.disabled)"
></el-date-picker>
<!-- 日期时间 日期有限制 选择范围:当前天及以后-->
<el-date-picker
v-if="item.type === 'dateTimelimit'"
type="datetime"
v-model="searchData[item.prop]"
:placeholder="item.placeholder || '选择日期时间'"
style="width: 100%"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-ddTHH:mm:ss"
:disabled="Boolean(item.disabled)"
:pickerOptions="endDateTimeLimitPickerOptions()"
></el-date-picker>
<!-- 对象日期时间 -->
<el-date-picker
v-if="item.type === 'objectDateTime'"
type="datetime"
v-model="searchData[item.prop][item.showProp]"
:placeholder="item.placeholder || '选择日期'"
style="width: 100%"
value-format="yyyy-MM-ddTHH:mm:ss"
:disabled="Boolean(item.disabled)"
></el-date-picker>
<!--开始时间结束时间-->
<div
class="RangeDateTime"
v-if="item.type === 'rangeDateTime'"
style="width: 100%; height: 100%"
>
<el-col :span="10">
<el-form-item :prop="item.prop + '.' + item.startDate">
<el-date-picker
type="datetime"
:placeholder="item.placeholder || '开始日期'"
v-model="searchData[item.prop][item.startDate]"
style="width: 100%"
:disabled="Boolean(item.disabled)"
value-format="yyyy-MM-ddTHH:mm:ss"
:pickerOptions="
startPickerOptions(searchData[item.prop][item.endDate])
"
></el-date-picker>
</el-form-item>
</el-col>
<el-col class="line" :span="4">-</el-col>
<el-col :span="10">
<el-form-item :prop="item.prop + '.' + item.endDate">
<el-date-picker
type="datetime"
:placeholder="item.placeholder || '结束日期'"
v-model="searchData[item.prop][item.endDate]"
style="width: 100%"
:disabled="Boolean(item.disabled)"
value-format="yyyy-MM-ddTHH:mm:ss"
:pickerOptions="
endPickerOptions(searchData[item.prop][item.startDate])
"
></el-date-picker>
</el-form-item>
</el-col>
</div>
<!-- 开关 -->
<el-switch
v-if="item.type === 'switch'"
v-model="searchData[item.prop]"
></el-switch>
<!--文件上传-->
<currenUpload
v-if="item.type === 'upload'"
:limit="item.limit"
:beforeUpload="beforeAvatarUpload"
:searchData="searchData[item.prop]"
@httpRequestfiles="httpRequestfiles($event, item.prop)"
@handleRemove="handleRemove($event, item.prop)"
>
</currenUpload>
<!--文件上传——列表形式-->
<currenUploadList
v-if="item.type === 'uploadList'"
:limit="item.limit"
:picExt="item.picExt"
:searchData="searchData[item.prop]"
@uploadListView="uploadListView"
@changeUpload="changeUpload($event, item)"
@handleRemove="handleRemove($event, item.prop)"
>
</currenUploadList>
<!-- 缩略图上传 -->
<currenUploadPictureCard
v-if="item.type === 'uploadPictureCard'"
:limit="item.limit"
:multiple="item.multiple"
:picExt="item.picExt"
:searchData="searchData[item.prop]"
@changeUpload="changeUpload($event, item)"
@handleRemove="handleRemove($event, item.prop)"
>
</currenUploadPictureCard>
<el-button
v-if="item.type === 'button'"
type="primary"
size="mini"
@click="item.click(item)"
>
{{item.buttonText}}
</el-button>
</el-form-item>
</el-col>
</el-row>
<slot></slot>
</el-form>
<div v-if="isHandle" class="formButton">
<!-- :style="{float:item.float}" 自定义按钮显示位置 -->
<el-button
v-for="(item, index) in searchHandle"
:key="item.label"
:type="item.type"
:size="item.size || size"
:loading="loading"
:style="{float:item.float}"
@click="submitForm(index,item)"
>{{ item.label }}</el-button
>
</div>
</div>
</template>
<script>
import currenUpload from "@/components/currenUpload";
import currenUploadList from "@/components/currenUploadList";
import currenUploadPictureCard from "@/components/currenUploadPictureCard";
import filterSelect from "@/components/filterSelect"
import { getMatchRegConformValue } from "@/utils/index"
export default {
name: "currenForm",
components: {
currenUpload,
currenUploadList,
currenUploadPictureCard,
filterSelect
},
props: {
loading: {
type: Boolean,
default: false,
},
labelPosition: {
type: String,
default: "right",
},
isHandle: {
type: Boolean,
default: true,
},
inline: {
type: Boolean,
default: false,
},
labelWidth: {
type: String,
default: "140px",
},
size: {
type: String,
default: "mini",
},
searchForm: {
type: Array,
default: () => {
return [];
},
},
searchHandle: {
type: Array,
default: () => {
return [];
},
},
searchData: {
type: Object,
default: () => {
return {};
},
},
searchOptions: {
type: Object,
default: () => {
return {};
},
},
rules: {
type: Object,
default: () => {
return {};
},
},
formSpan: {
type: Number,
default: 24,
},
hide: {
type: Boolean,
default: false,
},
},
data() {
return {
restaurants: [],
indeterminate: false,
selectLoading: false,
};
},
computed: {
startPickerOptions() {
return function (val) {
return {
disabledDate(time) {
if (val) {
return (
// time.getTime() > Date.now() ||
// time.getTime() > new Date(that.CreateFormData.endDate).getTime()
time.getTime() > val
);
}
// return time.getTime() > Date.now(); //实现1效果
},
};
};
},
endPickerOptions() {
// const that = this;
return function (val) {
return {
disabledDate(time) {
if (val) {
return (
// time.getTime() > Date.now() ||
// time.getTime() < new Date(that.CreateFormData.startDate).getTime()
time.getTime() < val
);
}
// return time.getTime() > Date.now(); //实现1效果
},
};
};
},
// 日期时间组件,选择范围:当前天及以后
endDateTimeLimitPickerOptions() {
return function () {
return {
disabledDate(time) {
return (
time.getTime() < Date.now() - 8.64e7
);
},
};
};
},
selectOptions() {
return (val) => {
if (val) {
let options = this.$staticOptions[val];
if (options) {
return options();
} else {
return [];
}
} else {
return false;
}
};
},
},
mounted() {
// 单选 , 默认设置
this.searchForm.forEach(item => {
if (item.type === 'radio') {
this.searchData[item.prop] = item.value + ''
}
if (item.type === 'checkbox') {
this.searchData[item.prop].push(item.value)
}
})
},
methods: {
// type=input情况下,框实时校验
itemOnKeyUp(item,value){
if(item.onkeyup){
return item.onkeyup()
}else{
if(value && item.validType){
this.searchData[item.prop]=getMatchRegConformValue(item.validType,value,item.pointNumberFixed)
}
}
},
// 数字类型input框onkeyup最大最小值处理
typeNumberOnkeyup(item,value){
if(value){
// 添加pointNumberFixed 可以输入小数
if (item.pointNumberFixed) {
let _fixed = item.pointNumberFixed ? Number(item.pointNumberFixed) : 100
let reg = new RegExp(`\\d+\\.?\\d{0,${_fixed}}`);
let _match = String(value).match(reg)
this.searchData[item.prop] = _match ? _match[0] : _match
} else {
let _match = String(value).match(/\d+/)//正整数
this.searchData[item.prop] = _match?_match[0]:_match
}
}
if(this.searchData[item.prop] > item.max){
this.searchData[item.prop] = item.max
}
if(this.searchData[item.prop] && this.searchData[item.prop] < item.min){
this.searchData[item.prop] = item.min
}
if(item.onkeyup)item.onkeyup()
},
//复选框全选
handleCheckAllChange(val,item) {
const options = []
if(val){
this.searchOptions[item.checkboxs].forEach(items=>{
options.push(items)
})
}
this.searchData[item.prop] = val ? options : [];
this.indeterminate = false;
},
//取消全选
handleCheckedCitiesChange(value,item) {
let checkedCount = value.length;
item.checkAll = checkedCount === this.searchOptions[item.checkboxs].length;
this.indeterminate = checkedCount > 0 && checkedCount < this.searchOptions[item.checkboxs].length;
},
inputPlaceholder(val, item, type, func) {
if (item.valueType) {
if (type == "focus") {
console.log("focus")
//影响必填项,2023-1-3 placeholder不处理
// val.target.placeholder = '0';
// if (val.target.value != "") {
// val.target.placeholder = val.target.value;
// val.target.value = "";
// }
} else if (type == "blur") {
console.log("blur")
// val.target.value = "0"
val.target.value = val.target.value.toString().replace(/[^\d.]/g,'')
// if (val.target.value == "") {
// // if (val.target.placeholder.indexOf('请输入') == -1) {
// val.target.value = val.target.placeholder;
// // }
// }
if(item.showProp){
if(val.target.value != ""){func[item.prop][item.showProp]= Number(val.target.value)}
}else{
if(val.target.value != ""){func[item.prop]= Number(val.target.value)}
}
// item.valueType
// ? (this.searchData[item.prop] = item.valueType(
// this.searchData[item.prop]
// ))
// : () => {
// return;
// }
}
}
},
querySearch(queryString, cb, val) {
const { options, optionsValue, optionsLabel } = val;
let func = val.focus;
let data = {};
if (queryString) {
data.filter = [
{
logic: "And",
column: optionsValue,
action: "Like",
value: queryString,
},
// {
// logic: "Or",
// column: optionsLabel,
// action: "Like",
// value: queryString
// }
];
}
func(data).then((res) => {
var restaurants = this.searchOptions["options"];
var results = queryString
? restaurants.filter(
this.createFilter(queryString, optionsValue, optionsLabel)
)
: restaurants;
results.forEach((key) => {
if (typeof optionsValue === "string") {
key.value = key[optionsValue] + "----" + key[optionsLabel];
} else {
key.value =
key[optionsValue[0]][optionsValue[1]] +
"----" +
key[optionsLabel];
}
});
// 调用 callback 返回建议列表的数据
cb(results);
});
},
createFilter(queryString, optionsValue, optionsLabel) {
return (restaurant) => {
if (typeof optionsValue === "string") {
restaurant.value =
restaurant[optionsValue] + "----" + restaurant[optionsLabel];
} else {
restaurant.value =
restaurant[optionsValue[0]][optionsValue[1]] +
"----" +
restaurant[optionsLabel];
}
return (
restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) !=
-1
);
};
},
handleSelect(item, val) {
let data = this.searchData;
if (!val.showProp) {
if (typeof val.optionsValue === "string") {
data[val.prop] = item[val.optionsValue];
} else {
data[val.prop] = item[val.optionsValue[0]][val.optionsValue[1]];
}
} else {
if (typeof val.optionsValue === "string") {
data[val.prop][val.showProp] = item[val.optionsValue];
} else {
data[val.prop][val.showProp] =
item[val.optionsValue[0]][val.optionsValue[1]];
}
}
this.$emit("push", item, val);
},
// filterSelect点击option事件
filterOptionSelectHandle(item,props,val){
this.searchData[props['prop']] = val
this.$emit("push", item, props);
},
// filterSelect点击清除事件
filterClearHandle(item){
this.searchData[item['prop']] = ""
this.$emit("clear",item)
},
// selectFocus (val, item) {
// this.selectLoading = true;
// let func = item.focus
// func({}).then(res => {
// this.selectLoading = false;
// })
// },
// dataFilter (query, item) {
// const { options, optionsValue, optionsLabel } = item
// let func = item.focus
// let data = {}
// this.selectLoading = true;
// if (query) {
// data.filter = {
// logic: "And",
// column: optionsLabel,
// action: "Like",
// value: query
// }
// }
// setTimeout(() => {
// func(data).then(res => {
// this.selectLoading = false;
// })
// }, 200);
// // this.options = [];
// },
submitForm(val,item) {
this.$emit("submitForm", val, this.$refs.form,item);
},
getDom(){
return this.$refs.form
},
handleClick(val) {
this.$emit("handleClick", val);
},
httpRequestfiles(val, item) {
this.searchData[item].push(val);
},
beforeAvatarUpload(val, data) {
const repeat = data.filter((item) => {
return item.name == val.name;
});
if (repeat.length != 0) {
this.$errorMsg("文件重复");
return false;
} else {
return true;
}
},
handleRemove(val, item) {
this.searchData[item] = val
},
changeUpload(val, item){
// 判断上传文件是否满足类型
let suffix = val.name.substring(val.name.lastIndexOf('.') + 1)
if (item.picExt.indexOf(suffix) === -1) {
this.$warningMsg('上传文件只能是 ' + item.picExt + '格式!')
this.searchData[item.prop] = []
return false
} else {
this.searchData[item.prop].push(val);
}
},
uploadListView() {
this.$emit('uploadListView')
},
radioChange(prop, val) {
this.$emit("radioChange", prop, val)
},
changeInput(prop, val) {
this.$emit("changeInput", prop, val)
},
clearInput(prop, val) {
this.$emit("clearInput", prop, val)
},
changeSelect(prop, val) {
this.$emit("changeSelect", prop, val)
},
restrictionRule(item, prop) {
if(prop) {
console.log('item',item)
console.log('prop', prop)
console.log('this.searchData', this.searchData)
console.log(this.searchData[prop])
if (this.searchData[prop]) {
return false
} else {
return true
}
} else {
return true
}
}
// 单一文件上传输入框——上传文件提示
// handleExceed (val) {
// this.$warningMsg('最多上传1个文件')
// }
// //自定义select搜索
// dataFilter (val, data) {
// if (!data) {
// return;
// } else {
// this.$emit(data, val);
// }
// },
},
};
</script>
<style lang="scss" scoped>
// .formButton {
// text-align: right;
// }
.inputNameberClass {
width: 100%;
}
.el-row {
::v-deep .el-form-item__content {
position: relative;
font-size: 14px;
}
.RangeDateTime {
::v-deep .el-col {
padding: 0 !important;
}
.line {
text-align: center;
}
}
}
::v-deep .el-form-item__label{
color: #999 !important;
font-weight: normal !important;
}
</style>