<template>
<a-row :gutter="24">
<a-col :span="24 / colNum" v-for="(cItem, cIndex) in list" :key="cIndex">
<a-row :gutter="24">
<a-col
:span="24 / cItem.length"
v-for="item in cItem"
:key="item.value"
>
<a-form-item
v-if="item.type != 'upload'"
:field="item.value"
:label="$t(item.label)"
:label-col-flex="labelWidth"
:rules="getFormRules(item.rule,item.label,item.type)"
>
<template v-if="type != 'detail'">
<!-- 下拉选择 -->
<a-select
v-if="item.type == 'select'"
v-model="filterForm[item.value]"
:placeholder="$t('numDigital.pleaseSelect')"
>
<a-option
v-for="option in optionsData.optionsObj[item.optionName]"
:value="option.code"
:key="option.code"
>{
{ option.value }}</a-option
>
</a-select>
<!-- 输入框 -->
<template v-if="item.type == 'input'">
<a-input
:max-length="20"
v-model="filterForm[item.value]"
:placeholder="$t('numDigital.pleaseEnter')"
/>
<span class="normal" v-if="item.units"> {
{
$t(item.units)
}}</span>
</template>
<!-- 数字输入框 -->
<!-- :formatter="formatter" :parser="parser" -->
<template v-if="item.type == 'numberInput'">
<a-input-number
max-length="13"
v-model="filterForm[item.value]"
:placeholder="$t('numDigital.pleaseEnter')"
:min="item.min"
:max="item.max"
:precision="getPrecision(item.precision)"
/>
<span class="normal" v-if="item.units"> {
{
$t(item.units)
}}</span>
</template>
<!-- 多行输入框 -->
<a-textarea
v-if="item.type == 'textArea'"
class="textarea"
:placeholder="$t('numDigital.pleaseEnter')"
v-model="filterForm[item.value]"
max-length="200"
/>
<!-- 单选框 -->
<a-space size="large" v-if="item.type == 'radio'">
<a-radio-group v-model="filterForm[item.value]">
<a-radio :value="1">{
{ $t('common.yes') }}</a-radio>
<a-radio :value="0">{
{ $t('common.no') }}</a-radio>
</a-radio-group>
</a-space>
<!-- 日期选择 -->
<a-date-picker
style="width:100%"
value-format="YYYY-MM-DD "
v-if="item.type == 'datePicker'"
v-model="filterForm[item.value]"
/>
<!-- 日期范围 --> <!-- :value-format="item.valueFormat?item.valueFormat:'YYYY-MM-DD'" -->
<a-range-picker
v-if="item.type == 'rangePicker'"
@change="timeChange(item)"
v-model="filterForm[item.value]"
/>
<!-- 月份选择 -->
<a-month-picker
style="width:100%"
v-if="item.type == 'monthPicker'"
v-model="filterForm[item.value]"
/>
<!-- 月份范围 -->
<a-range-picker
mode="month"
v-if="item.type == 'monthRangePicker'"
v-model="filterForm[item.value]"
/>
<!-- 输入范围 -->
<template v-if="item.type == 'inputRange'">
<a-input
max-length="20"
v-model="filterForm[item.value[0]]"
:placeholder="$t('numDigital.pleaseEnter')"
/>
<span class="normal"> {
{ $t('lease.to')}} </span>
<a-input
max-length="20"
v-model="filterForm[item.value[1]]"
:placeholder="$t('numDigital.pleaseEnter')"
/>
<span class="normal" v-if="item.units"> {
{
$t(item.units)
}}</span>
</template>
<!-- 输入数字范围 -->
<template v-if="item.type == 'numberInputRange'"> <!-- :formatter="formatter" :parser="parser" -->
<a-input-number
max-length="13"
v-model="filterForm[item.value[0]]"
:placeholder="$t('numDigital.pleaseEnter')"
:precision="getPrecision(item.precision)"
:min="item.min"
:max="item.max"
/>
<span class="normal"> {
{ $t('lease.to') }} </span>
<a-input-number
max-length="13"
v-model="filterForm[item.value[1]]"
:placeholder="$t('numDigital.pleaseEnter')"
:precision="getPrecision(item.precision)"
:min="filterForm[item.value[0]]"
:max="item.max"
/>
<span class="normal" v-if="item.units"> {
{
$t(item.units)
}}</span>
</template>
</template>
<slot name="detail" :data="item" />
</a-form-item>
<template v-if="item.type == 'upload'">
<fileUploader ref="myfileUploader" @onsuccess="uploadOnsuccess" :type="type" :showUploadBtn="type=='detail'?false:true" :fileList="file.fileList" >
<template #button>
<a-button type="primary">
<template #icon>
<icon-upload />
</template>
<template #default>{
{ $t('common.uploadAttach') }}</template>
</a-button>
</template>
</fileUploader>
</template>
</a-col>
</a-row>
</a-col>
</a-row>
</template>
<script lang="ts" setup>
import { defineProps, defineEmits, ref,computed, onMounted, watch,onBeforeMount,defineExpose ,nextTick,reactive,getCurrentInstance} from 'vue';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
import useLoading from '@/hooks/loading';
const { loading, setLoading } = useLoading();
import { getWebDictList } from '@/api/user';
import fileUploader from '@/components/uploader/FileUploader.vue';
import { valid } from 'mockjs';
const emit = defineEmits(['uploadOnsuccess']);
const props = defineProps({
labelWidth: {
type: String,
default: '130px'
},
type: {
type: String,
default: 'search'
},
list: Array,
filterForm: Object,
colNum: Number,
});
onMounted(()=>{
getAllOptions();
})
/****文件列表处理****/
watch(
()=>props.filterForm.attachment,
(val)=>{
getFileList(val);
},
{deep:true, }
);
const file=reactive({fileList:[]});
const getFileList=(attachment:any)=>{
if(attachment){
let attachment=props.filterForm.attachment;
let attachmentName=props.filterForm.attachmentName;
const attachmentArr=attachment.split(',');
const attachmentNameArr=attachmentName?attachmentName.split(','):[];
let saveArr=[];
for(let i=0;i<attachmentArr.length;i++){
let name=attachmentArr[i].substring(attachmentArr[i].lastIndexOf('/') + 1);
let itemObj={
id:i,
name:attachmentNameArr[i]||name,
url:attachmentArr[i]
}
saveArr.push(itemObj);
}
file.fileList=saveArr;
}else{
file.fileList=[];
}
}
const timeChange = (item:any) => {
if(props.filterForm[item.value]&&props.filterForm[item.value].length>0){
props.filterForm[item.startTimeField || "startTime"] =props.filterForm[item.value][0] + " 00:00:00";
props.filterForm[item.endTimeField || "endTime"] =props.filterForm[item.value][1] + " 23:59:59";
}else{
props.filterForm[item.startTimeField || "startTime"]="";
props.filterForm[item.endTimeField || "endTime"] =""
}
};
//对下拉框选项处理
let optionsData=reactive({
optionsObj:{}
});
const getAllOptions=()=>{
const lists=props.list;
lists.forEach(row=>{
row.forEach(col=> {
if(col.type=='select'){
getOptionsFun(col.optionName);
}
});
})
}
const getOptionsFun=async(typeName:any)=>{
setLoading(true);
try {
const res = await getWebDictList({
type: typeName
});
if (res.code == 0) {
const list:any|undefined|null=res.data||[];
optionsData.optionsObj=Object.assign(optionsData.optionsObj,{[typeName]:list});
}
}catch(err){
} finally {
setLoading(false);
}
}
watch(
()=>props.filterForm,
(val)=>{
transFormToNumber(props.list);
},
{deep:true}
);
//转换成数字
const transFormToNumber=(rowList:any)=>{
for(let i=0;i<rowList.length;i++){
for(let j=0;j<rowList[i].length;j++){
const itemType=rowList[i][j].type;
const itemValue=rowList[i][j].value;
if(itemType=="numberInput"&&props.filterForm[itemValue]){
const _val=props.filterForm[itemValue];
props.filterForm[itemValue]=Number(_val);
}
if(itemType=="numberInputRange"&&props.filterForm[itemValue[0]]&&props.filterForm[itemValue[1]]){
const _val1=props.filterForm[itemValue[0]];
const _val2=props.filterForm[itemValue[1]];
props.filterForm[itemValue[0]]=Number(_val1)
props.filterForm[itemValue[1]]=Number(_val2)
}
}
}
}
//上传附件
const uploadOnsuccess = (files: any) => {
emit('uploadOnsuccess', files);
};
const formatter = (value:any) => {
const values = value.split('.');
values[0] = values[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return values.join('.');
};
const parser = (value:any) => {
const val=value.replace(/,/g, '');
return val;
};
//数字输入精度
const getPrecision=computed(()=>{
return (precisionVal:Number)=>{
if(precisionVal){
return precisionVal
}else if(precisionVal==0){
return precisionVal
}else{
return 2;
}
}
})
const toNumber=computed(()=>{
return (val:any)=>{
return Number(val)
}
})
//表单校验规则
const getFormRules=computed(()=>{
return (rule:any,label:any,type:any)=>{
let typeMessage="";
if(type=='select'||type=='radio'||type=='datePicker'||type=='rangePicker'){
typeMessage='numDigital.pleaseSelect'
}else{
typeMessage='numDigital.pleaseEnter'
}
if(rule&&rule.required){
let ruleArr:any=[{required:true,message:t(typeMessage) + t(label)}];
return ruleArr;
}else{
return []
}
}
//
})
</script>
<style lang="less" scoped>
.normal {
font-size: 14px;
color: var(--color-text-2);
flex: none;
}
.textarea {
/* width: 464px;
height: 120px; */
}
:deep{
.arco-form-item-label-col > .arco-form-item-label{
white-space: nowrap;
overflow: hidden;
}
.arco-radio-group .arco-radio{
margin-right:0;
}
}
</style>
页面引入使用
<a-form>
<a-row :gutter="24">
<a-col :span="buttonStyle=='column'?22:20">
<formItem :colNum='colNum' :list="formList" :filterForm="form" :labelWidth="labelWidth" />
</a-col>
<a-col :span="buttonStyle=='column'?2:4">
<div class="btn-wrap">
<template v-if="buttonStyle=='column'">
<a-row justify="right">
<a-form-item>
<a-button @click="submitForm(filterForm)" type="primary">{
{
$t('common.search')
}}</a-button>
</a-form-item>
</a-row>
<a-row class="resert">
<a-form-item>
<a-button @click="resetForm">{
{ $t('common.reset') }}</a-button>
</a-form-item>
</a-row>
</template>
<template v-else>
<a-space :size="gutter">
<a-button @click="submitForm(filterForm)" type="primary">{
{
$t('common.search')
}}</a-button>
<a-button @click="resetForm">{
{ $t('common.reset') }}</a-button>
</a-space>
</template>
</div>
</a-col>
</a-row>
</a-form>
form: {
schoolName: '',
assetName: '',
acquisitionDate: '',
isByEducation: '',
isEducationBuilding: '',
isHire: '',
area: '',
situation: '',
startDate: '',
endDate: '',
price: '',
annualIncome: '',
tenantry: '',
leasePurpose: '',
approvalDepartment: '',
remark: '',
attachment: '',
attachmentName:"",
fileIds: []
},
formList: [
{
id: 1,
title: 'lease.add.basicInformation',
rows: [
[
{
type: 'select',
value: 'schoolName',
label: 'lease.campusName',
options: [],
optionName:'campus_name',
rule: {
required: true
}
}
],
[
{
type: 'input',
value: 'assetName',
label: 'lease.assetName',
rule: { required: true }
}
],
[
{
type: 'datePicker',
value: 'acquisitionDate',
label: 'lease.acquisitionDate',
rule: { required: true }
}
],
[
{
type: 'input',
value: 'propertyOwner',
label: 'lease.possessor',
rule: { required: true }
}
],
[
{
type: 'radio',
value: 'isEducationBuilding',
label: 'lease.teachingBuilding',
rule: { required: true }
}
],
[
{
type: 'numberInput',
value: 'area',
label: 'lease.area',
units: 'lease.squareMeter',
min: '0',
max: '',
rule: { required: true }
}
],
[
{
type: 'input',
value: 'situation',
label: 'lease.situation',
rule: { required: true }
}
]
]
},
{
id: 2,
title: 'lease.add.leasingAndLendingAssets',
rows: [
[
{
type: 'datePicker',
value: 'startDate',
label: 'lease.startDate',
rule: { required: true }
}
],
[
{
type: 'datePicker',
value: 'endDate',
label: 'lease.endDate',
rule: { required: true }
}
],
[
{
type: 'numberInput',
value: 'price',
label: 'lease.add.unitPrice',
units: 'lease.add.priceUnits',
min: '0',
rule: { required: true }
}
],
[
{
type: 'numberInput',
value: 'annualIncome',
label: 'lease.add.income',
units: 'lease.add.incomeUnits',
min: '0',
precision: 6,
rule: { required: true }
}
],
[
{
type: 'input',
value: 'tenantry',
label: 'lease.lessee',
rule: { required: true }
}
],
[
{
type: 'input',
value: 'leasePurpose',
label: 'lease.lendLease',
rule: { required: true }
}
]
]
},
{
id: 3,
title: 'lease.add.otherInformation',
rows: [
[
{
type: 'input',
value: 'approvalDepartment',
label: 'lease.department',
rule: { required: true }
}
],
[
{
type: 'radio',
value: 'isByEducation',
label: 'lease.add.educationAudited',
rule: { required: true }
},
{
type: 'radio',
value: 'isHire',
label: 'lease.publicRent',
rule: { required: true }
}
],
[
{
type: 'textArea',
value: 'remark',
label: 'common.remarks',
rule: { required: false }
}
]
]
},
{
id: 4,
title: 'lease.add.attachment',
rows: [
[
{
type: 'upload',
value: 'fileIds',
label: '',
rule: { required: false }
}
]
]
}
],
页面效果: