vue element 封装表单

背景:

在前端系统开发中,系统页面涉及到的表单组件比较多,所以进行了简单的封装。封装的包括一些Form表单组件,如下:input输入框、select下拉框、等

实现效果:

理论知识:

表单组件官方链接:点击跳转

封装组件:

封装组件的思路:

 不封装element组件,每一个input组件绑定一个form对象,例如官网。

简单封装element组件,利用for循环生成form表单的每一项el-form-item。

进一步封装,利用判断表单组件的类型,是input、select或者其它表单组件。

终极封装,把el-form表单封装成一个独立的表单,自定义命名为AreaFormItem.vue;然后单页面vue调用AreaFormItem.vue传参以及表单数据回显等操作。

封装组件的过程: 

1.不封装表单组件,代码如下: 

实现代码:【表单组件未封装】

<el-form ref="ruleForm" :model="state.form" label-width="auto" :rules="rules" class="form-box"><el-row class="form-row"><el-col :span="5" :gutter="20" style="padding-left: 0px"><el-form-item label="航次" prop="voyageNo"><el-input v-model="state.form.voyageNo" placeholder="请输入航次" /></el-form-item></el-col><el-col :span="4" :gutter="20" style="padding-left: 10px"><el-form-item label="船名" prop="name"><el-input v-model="state.form.name" placeholder="请输入船名" /></el-form-item></el-col><el-col :span="4" :gutter="20" style="padding-left: 10px"><el-form-item label="装港" prop="loadName"><el-input v-model="state.form.loadName" placeholder="请输入装港" /></el-form-item></el-col><el-col :span="5" :gutter="20" style="padding-left: 10px"><el-form-item label="卸港" prop="dischargName"><el-input v-model="state.form.dischargName" placeholder="请输入卸港" /></el-form-item></el-col><el-col :span="5" :gutter="20" style="padding-left: 10px"><el-form-item label="卸港" prop="cargoType"><el-input v-model="state.form.cargoType" placeholder="请输入卸港" /></el-form-item></el-col></el-row></el-form>

备注:因为是横着的表单,这里加入了el-row和el-col 。

2.表单组件封装,for循环渲染表单组件input:

//html
<el-form ref="ruleForm" :model="state.form" label-width="auto" :rules="rules" class="form-box"><el-row class="form-row"><el-col :span="item.span || 5" :gutter="20" style="padding-right: 10px" v-for="(item, index) in formItems":key="index"><el-form-item :label="item.label" :prop="item.key"><el-input v-model="state.form[item.key]" :placeholder="item.placeholder || '请输入'" /></el-form-item></el-col></el-row></el-form>//涉及到的变量
const state = reactive({form: {name: '',voyageNo: '',loadName: '',dischargName: '',cargoType: ''},
})
const formItems = [{type: 'input',label: '船名',key: 'name',placeholder: '请输入或者选择船名'},{type: 'input',label: '航次',key: 'voyageNo',placeholder: '请输入或者选择航次'},{type: 'select',label: '装港',key: 'loadName',placeholder: '请输入或者选择装港'},{type: 'select',label: '卸港',key: 'dischargName',placeholder: '请输入或者选择始港'},{type: 'input',label: '货种',span : 4,key: 'cargoType',placeholder: '请输入或者选择货种',}
]

3.封装一个input或者select下拉列表,封装如下:

<el-form ref="ruleForm" :model="state.form" label-width="auto" :rules="rules" class="form-box"><el-row class="form-row"><el-col :span="item.span || 5" :gutter="20" style="padding-right: 10px"v-for="(item, index) in formItems" :key="index"><el-form-item :label="item.label" :prop="item.key"><el-input v-model="state.form[item.key]" :placeholder="item.placeholder || '请输入'"v-if="item.type === 'input'" /><template v-else-if="item.type === 'select'"><el-select v-model="state.form[item.key]" :clearable="true":loading="routeState.loading_startPoint" :multiple="false":remote-method="(query) => remoteMethod_Point(query, 'cargoType')"filterable placeholder="请输入或者选择货种" remote reserve-keyword@change="(value) => blur_Point(value, 'cargoType', '')"@clear="clear_select('cargoType')"><el-option v-for="item in routeState.options_startPoint" :key="item.value":label="item.label" :value="item.label" /></el-select></template></el-form-item></el-col></el-row></el-form>
//涉及到的数据
const routeState = reactive({loading_startPoint:false,options_startPoint:[]
})

4.终极封装,把上面的form表单封装成一个vue组件,自定义命名为 AreaFormItem.vue,

AreaFormItem.vue组件,封装如下:
<template><el-form :model="data.formInline" class="area-from" :inline="true" :label-position="'left'" ref="ruleAreaFormRef":rules="data.rules"><template v-for="(item, index) in props.formItems" :key="index"><template v-if="item.type &&!['location','medium','password','sexRadio','coordinate','radio','textarea','multipleSelect','uploadFile','uploadSingleImg',].includes(item.type)"><el-form-item :label="item.label" :label-width="item.labelWidth" :prop="item.key" :class="item.class" :style="{'max-width': item.width || '50%',width: item.specialWidth || item.width,}" v-if="item.linkageShow === undefined || item.linkageShow"><template v-if="item.type == 'select'"><el-select v-model="data.formInline[item.key]" placeholder="请选择":style="{ width: item.specialWidth || item.width || '10vw' }" :disabled="item.isEditAbled && data.isAbled":filterable="item.filterable" :filter-method="(filterVal) => {handleSelectEdit(filterVal, item);}" @blur="() => {item.filterable &&data.editSelectValue &&(data.formInline[item.key] = data.editSelectValue);}" @change="(val) => {handleSelectEdit(val, item);searchChange(item.linkageKey,item.optionsData,data.formInline[item.key],item.linkageDraw,item.autoPosition,item.dynamicLinkageKey,props.formItems,item.linkageKeyList,item);}"><template v-if="item.optionsData.length"><el-option v-for="(optionItem, index) in item.optionsData" :key="index" :label="optionItem.label":value="optionItem.value" /></template><template v-else><el-option v-for="(optionItem, index) in data.selectData" :key="index" :label="optionItem.label":value="optionItem.value" /></template></el-select></template><template v-if="item.type == 'selectTree'" style=".el-select {width: '10vw';}"><el-tree-select v-model="data.formInline[item.key]" :placeholder="item.placeholder || '请选择所属区域'":style="{ width: item.specialWidth || item.width || '10vw' }" :data="data.treeData":props="data.defaultProps" check-strictly clearable :multiple="item.multiple || false":disabled="item.disabled || false" @change="(value) => handlechange(value, item.limit, item.isJump || true)" :filterable="item.filterable || false"></el-tree-select></template><template v-if="item.type == 'treeMuiltSelect'" style=".el-select {width: '10vw';}"><el-tree-select v-model="data.formInline[item.key]" :placeholder="item.placeholder || '请选择渡口'":style="{ width: item.specialWidth || item.width || '10vw' }" :data="data.treeDataList":props="item.optionParam || data.defaultProps" :multiple="item.multiple || false" :collapse-tags="true":collapse-tags-tooltip="true" :max-collapse-tags="1" clearable :disabled="item.disabled || false"></el-tree-select></template><template v-if="item.type == 'treeLocationSelect'" style=".el-select {width: '10vw';}"><el-tree-select v-model="data.formInline[item.key]" :placeholder="item.placeholder || '请选择区域下的渡口'":style="{ width: item.specialWidth || item.width || '10vw' }" :data="data.treeLocationSelect":props="item.optionParam || data.defaultProps" :multiple="item.multiple || false" :collapse-tags="true":collapse-tags-tooltip="true" :max-collapse-tags="1" clearable :disabled="item.disabled || false" :check-strictly="false"default-expand-all @change="(value) => handleSelectchange(value, item)":filterable="item.filterable || false" :filter-method="(filterVal) => {filtertreeLocationSelect(filterVal, item, 'treeLocationSelect');}" @blur="blur(item, 'treeLocationSelect')"></el-tree-select></template><template v-if="item.type == 'remoteSelect'"><el-select v-model="data.formInline[item.key]" filterable remote :placeholder="item.placeholder"remote-show-suffix :remote-method="(query) => {remoteMethod(query, item);}" :loading="data.remoteSelectLoading" @change="(val) => {item.getSelectRemoteValue &&item.getSelectRemoteValue(val, data.remoteSelectData);}" :disabled="item.isEditAbled && data.isAbled"><el-option v-for="optionItem in data.remoteSelectData" :key="optionItem.value" :label="optionItem.label":value="optionItem.value" /></el-select></template><template v-if="item.type == 'input'"><el-input v-model.trim="data.formInline[item.key]" placeholder="请输入" clearable @clear="searchChange":disabled="(item.isEditAbled && data.isAbled) || item.disabled":style="{ width: item.inputWidth || '10vw' }" :readonly="item.isReadonly || false"><template #suffix v-if="item.suffix">{{ item.suffix }}</template></el-input></template><template v-if="item.type == 'checkBox'"><div class="warn-type"><el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="(state) => {handleCheckAllChange(state, item.key);}" v-if="item.optionCheckAll">全部</el-checkbox><el-checkbox-group v-model="data.formInline[item.key]" @change="handleCheckedChange"><el-checkbox v-for="checkItem in item.optionsData" :key="checkItem.value" :label="checkItem.value":value="checkItem.value">{{ checkItem.label }}</el-checkbox></el-checkbox-group></div></template><template v-if="item.type == 'inputNumber'"><el-input v-model.trim.number="data.formInline[item.key]" placeholder="请输入数字" clearable@clear="searchChange" :disabled="item.isEditAbled && data.isAbled" style="width: 10vw":readonly="item.isReadonly || false" oninput="value = value.replace(/[^\d.]/g,'')"><template #suffix v-if="item.suffix">{{ item.suffix }}</template></el-input></template><template v-if="item.type == 'inputPhoneNumber'"><el-input v-model.trim.number="data.formInline[item.key]" placeholder="请输入数字" clearable@clear="searchChange" :disabled="item.isEditAbled && data.isAbled":style="{ width: item.inputWidth || '10vw' }" :readonly="item.isReadonly || false"oninput="value = value.replace(/[^\d.]/g,'')"><template #suffix v-if="item.suffix">{{ item.suffix }}</template></el-input></template><template v-if="item.type == 'cascader'"><el-cascader v-model="data.formInline.cityValue" :options="data.citiesData" :props="data.cityDefalut"@change="citySelectChange" style="width: 10vw" /></template><template v-if="item.type == 'datePicker'"><el-date-picker v-model="data.formInline[item.key]" type="datetime" placeholder="请选择":default-time="item.defaultTime || defaultTime" value-format="YYYY-MM-DD HH:mm:ss":style="{ width: item.specialWidth || '10vw' }" :readonly="item.isReadonly || false":disabled-date="item.disabledDate" /></template><template v-if="item.type == 'timePicker'"><el-time-picker v-model="data.formInline[item.key]" placeholder="请选择时间":default-time="item.defaultTime || defaultTime" value-format="HH:mm:ss":style="{ width: item.specialWidth || '10vw' }" :readonly="item.isReadonly || false":disabled-date="item.disabledDate" /></template><template v-if="item.type == 'dateNoTimePicker'"><el-date-picker v-model="data.formInline[item.key]" type="date" placeholder="请选择":default-time="item.defaultTime || defaultTime" value-format="YYYY-MM-DD":style="{ width: item.specialWidth || '10vw' }" :readonly="item.isReadonly || false":disabled-date="item.disabledDate" /></template></el-form-item></template><template v-if="item.type == 'multipleSelect'"><div class="select-area"><el-form-item :label="item.label" :label-width="item.labelWidth" :prop="item.key"><el-select v-model="data.formInline[item.key]" multiple clearable collapse-tags:placeholder="item.placeholder" popper-class="custom-header" :max-collapse-tags="1"style="width: 100%; height: 50px" @change="(val) => {item.selectOptionChange(val, item);}"><template #header v-if="item.optionsData.length"><el-checkbox v-model="item.checkAll" :indeterminate="item.indeterminate" @change="(val) => {item.handleCheckAll(val, item, data.formInline);}">全部区域</el-checkbox></template><el-option v-for="(optionItem, index) in item.optionsData" :key="index" :label="optionItem.label":value="optionItem.value" /></el-select></el-form-item></div></template><template v-if="item.type == 'radio'"><div class="warning-level" v-if="item.editShow === undefined ? true : !data.isAbled && !item.editShow" :style="{display:(item.onlySingleSelect || item.onlySingleSelect) &&'inline-block',width: item.width || '100%',}"><el-form-item :label="item.label" :label-width="item.labelWidth" :prop="item.key"v-if="!item.onlyDrawType && !item.hiddenFormItem"><el-radio-group v-model="data.formInline[item.key]" @change="(val) =>item.linkageAction? finallyLinkageSolve(item): warningLevelChange(val)"><template v-if="item.onlySingleSelect"><el-radio v-for="(aitem, aindex) in item.optionsData" :key="aindex" :label="aitem.value">{{ aitem.label}}</el-radio></template><template v-else><el-radio :label="1">一级</el-radio><el-radio :label="2">二级</el-radio><el-radio :label="3">三级</el-radio></template></el-radio-group></el-form-item><el-form-item :label="'绘制类型:'" :label-width="item.labelWidth" :prop="'drawType'"v-if="!item.onlySingleSelect && data.showDraw"><el-select v-model="data.formInline.drawType" placeholder="请选择" @change="drawTypeChange"style="width: 10vw"><el-option v-for="(optionItem, index) in data.drawTypes" :key="index" :label="optionItem.label":value="optionItem.value" /></el-select></el-form-item></div></template><template v-if="item.isBufferArea && !item.hiddenFormItem"><div class="warning-distance"><template v-for="(bufferItem, bufferIndex) in data.bufferData" :key="bufferIndex"><template v-if="bufferItem.level <= data.formInline.level"><el-form-item :label="bufferItem.label" :label-width="bufferItem.labelWidth" :prop="bufferItem.key"><el-input v-model.trim="data.formInline[bufferItem.key]" style="width: 4.2vw" placeholder="请输入"clearable></el-input><span class="unit">m</span></el-form-item></template></template></div></template><template v-if="item.type && item.type == 'textarea'"><div class="area-remark" :style="{ 'margin-top': item.marginTop || '0px' }"v-show="!item.conditionShow || item.conditionShow(props.formItemsVal)"><el-form-item :label="item.label" :label-width="item.labelWidth" :prop="item.key" :class="item.class"><el-input v-model="data.formInline[item.key]" :placeholder="item.placeholder || '请输入备注信息'" type="textarea":disabled="item.isEditAbled && data.isAbled" /></el-form-item></div></template><template v-if="item.type && item.editShow === undefined? item.type == 'coordinate': item.type == 'coordinate' && !data.isAbled && !item.editShow"><div class="cordinate-container"><el-form-item :label="item.label" :label-width="item.labelWidth" :prop="item.key"><div class="wrapper"><div class="row-input-box" v-for="(columnItem, index) in tableCloumn" :key="index"><div class="row-name">{{ columnItem.label }}</div><div class="input-item" v-for="(inpItem, ipIndex) in columnItem.inpModelParam" :key="ipIndex"><el-tooltip placement="top" :manual="true" :content="inpItem.msg"><el-input v-model="data.coordinate[inpItem.value]"></el-input></el-tooltip><div class="inp-unit">{{ inpItem.label }}</div></div></div></div><div class="box"><img :src="getAssetsFile('buttons/select_point.png')" @click="drawArea" /></div></el-form-item></div></template><template v-if="item.type == 'sexRadio'"><el-form-item :label="item.label" :label-width="item.labelWidth" :prop="item.key"><el-radio-group v-model="data.formInline[item.key]"><el-radio :label="1">男</el-radio><el-radio :label="2">女</el-radio></el-radio-group></el-form-item></template><template v-if="item.editShow === undefined? item.type == 'password': item.type == 'password' && !data.isAbled && !item.editShow"><el-form-item :label="item.label" :label-width="item.labelWidth" :prop="item.key" :class="item.class"><el-input v-model="data.formInline[item.key]" placeholder="请输入" type="password" autocomplete="new-password"show-password style="width: 10vw" /></el-form-item></template><template v-if="item.type == 'uploadFile'"><el-form-item :label="item.label" :label-width="item.labelWidth" :prop="item.key"><el-input v-model="data.formInline[item.key]" :placeholder="item.placeholder || data.headerResult.placeholder || '请输入'" clearable style="width: 245px" @clear="(value) =>fileClear('fileClear', data.headerResult.fileName, item)"><template #append><div class="opration-box" v-if="item.option"><div v-for="oprationItem in item.option" :key="oprationItem.text"><el-tooltip class="box-item" effect="dark" :content="oprationItem.text" placement="top"><template v-if="oprationItem.info == 'upload'"><el-upload ref="uploadRef" class="upload-demo" :show-file-list="false" :auto-upload="true"accept=".docx,.pdf,.doc" :action="oprationItem.params.importUrl":data="oprationItem.uploadParames" :headers="{ Authorization: store.userInfo.token }":on-success="(info) => handleResult('success', info, oprationItem)" :on-error="(info) => handleResult('error', info)"><img :src="upIcon" style="padding: 0 7px" /></el-upload></template><template v-else><img :src="upIcon" style="padding: 0 7px" @click="handleOpenDialog(oprationItem.params, oprationItem)" /></template></el-tooltip></div></div></template></el-input></el-form-item></template><template v-if="item.type == 'uploadMuliteImg'"><el-form-item :label="item.label" :label-width="item.labelWidth" :prop="item.key" :style="{width: item.specialWidth || item.width || '10vw',maxWidth: item.specialWidth || item.width || '10vw',}"><el-upload :auto-upload="false" list-type="picture-card" :on-preview="handlePictureCardPreview":on-change="uploadSingleImg" :limit="5" :file-list="upImgState.fileList"><el-icon v-if="upImgState.fileList.length == 0"><Plus /></el-icon></el-upload><el-dialog v-model="upImgState.dialogVisible"><img :src="upImgState.dialogImageUrl" alt="Preview Image" style="width: 100%" /></el-dialog></el-form-item></template><template v-if="item.type == 'uploadSingleImg'"><el-form-item :label="item.label" :label-width="item.labelWidth" :prop="item.key" :style="{width: item.specialWidth || item.width || '10vw',maxWidth: item.specialWidth || item.width || '10vw',}"><el-upload list-type="picture-card" :limit="1" :file-list="data.formInline[item.key]" :style="{width: item.width || '10vw',height: item.width || '10vw',}" :action="item.option.importUrl" :data="item.option.uploadParames" :show-file-list="true":headers="{ Authorization: store.userInfo.token }":on-success="(info) => uploadSingleImg('success', info, item)":on-error="(info) => uploadSingleImg('error', info)" :before-upload="beforeUploadSingleImg" :before-remove="(info) => beforeRemoveSingleImg('remove', info, item)" :on-preview="handlePictureCardPreview" accept="image/jpeg,image/png" :disabled="data.formInline[item.key] && data.formInline[item.key].length? true: false"><el-icon class="avatar-uploader-icon"><Plus /></el-icon><template #file="{ file }"><div><img class="el-upload-list__item-thumbnail" :src="file.url" alt="" /><span class="el-upload-list__item-actions"><span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)"><el-icon><zoom-in /></el-icon></span><span class="el-upload-list__item-delete" @click="beforeRemoveSingleImg('remove', file, item)"><el-icon><Delete /></el-icon></span></span></div></template></el-upload><el-dialog v-model="upImgState.dialogVisible"><img :src="upImgState.dialogImageUrl" alt="Preview Image" style="width: 100%" /></el-dialog></el-form-item></template></template></el-form>
</template><script setup>
import { max, merge } from "lodash";
import { useAxios } from "@/utils/useAxios";
import axios from "axios";
import { transformObject, getAssetsFile, debounce } from "@/utils";
import { arrayToTreeRec } from "@/utils/utils.js";
import { mapDrawGraph } from "@/utils/map/mapDraw";
import { reactive, ref, watch } from "vue";
import useShoreBasedStore from "@/store/index";
import { BASEUrl } from "@/utils/request";
import { locationPoint } from "@/assets/js/commont";
import upIcon from "@/assets/images/table/upload.png";
const store = useShoreBasedStore();
const defaultTime = new Date();
const tableCloumn = [{label: "经度",prop: "lat",type: "lat",inpModelParam: [{ value: "jd", label: "度", msg: "大于等于0小于等于180的整数" },{ value: "jf", label: "分", msg: "大于等于0小于60的整数" },{ value: "jm", label: "秒", msg: "大于等于0小于60" },],},{label: "纬度",prop: "lon",type: "lon",inpModelParam: [{ value: "wd", label: "度", msg: "大于等于0小于等于90的整数" },{ value: "wf", label: "分", msg: "大于等于0小于60的整数" },{ value: "wm", label: "秒", msg: "大于等于0小于60" },],},
];let props = defineProps({dialogType: {type: String,default: "",},formItems: {type: Array,default: [],},formRules: Object,formItemsVal: Object,MapData: Object,/* tableData: {type: Array,default: [],}, */inputTableData: {type: Array,default: [],},
});
const ruleAreaFormRef = ref();const validateInteger = (rule, value, callback) => {if (Number(value) > 0) callback();else callback(new Error("请输入大于零的数字"));
};const data = reactive({formInline: {drawType: "3", //绘制类型,默认是面level: "2",tempObj: {}, //临时的选中lable},coordinate: {jd: "",jf: "",jm: "",wd: "",wf: "",wm: "",},selectData: [],remoteSelectData: [],count: 0, //下拉列表请求接口的  次数bufferData: [{ label: "一级缓冲距离:", level: 1, key: "buffDistance1" },{ label: "二级缓冲距离:", level: 2, key: "buffDistance2" },{ label: "三级缓冲距离:", level: 3, key: "buffDistance3" },],drawTypes: [{value: "1",label: "点",},{value: "2",label: "线",},{value: "3",label: "面",},],rules: {level: [{ required: true, trigger: "change" }],buffDistance1: [{ required: true, message: "一级缓冲距离不能为空", trigger: "blur" },{ validator: validateInteger, rigger: "blur" },],buffDistance2: [{ required: true, message: "二级缓冲距离不能为空", trigger: "blur" },{ validator: validateInteger, rigger: "blur" },],buffDistance3: [{ required: true, message: "三级缓冲距离不能为空", trigger: "blur" },{ validator: validateInteger, rigger: "blur" },],},cityDefalut: {label: "name",value: "code",children: "cities",},citiesData: [],isAbled: false,showDraw: true,clearFlag: null, //联动值切换时清空初始化标志editSelectValue: "",remoteSelectLoading: false, //可以输入搜索的下拉框headerApi: {},headerResult: {fileName: "",address: "",placeholder: "点击右侧按钮进行上传文件",},resTreeData: [],treeData: [],treeDataList: [],treeLocationSelect: [],storeTrseeData: [],defaultProps: {label: "name",value: "pid",},
});
const emit = defineEmits(["searchChange", "drawTypeChange", "controlDraw"]);
const searchChange = (linkageKey,optionsData,target,linkageDraw,autoPosition,dynamicLinkageKey,list,linkageKeyList,targetItem
) => {if (target?.length == 9) {data.formInline.tempObj = optionsData?.filter((item) => {return item.value === target;});}if (linkageDraw) {data.showDraw = linkageDraw(target);emit("controlDraw", data.showDraw);}if (linkageKey) {if (optionsData.length) {//联动下拉数据静态const result = optionsData.find((item) => {return item.value === target;});data.clearFlag = target;if (result?.url) {const buildData = {url: result.url,optionParam: result.optionParam,};getSelectData(buildData);} else {data.selectData = [{label: "假数据",value: "test",},];}} else {//联动下拉数据动态获取}}if (autoPosition) {let positionTaget = null;if (data.formInline.itemsString && data.formInline.itemsString === target) {positionTaget = JSON.parse(target).guid;} else {positionTaget = target;}mapData.MapData.location(mapData._layer.layers["windFarmArea"],positionTaget,12,mapData._layer);}if (dynamicLinkageKey) {const linkagedTaget = list.find((item) => item.key === dynamicLinkageKey);data.formInline[dynamicLinkageKey] = "";getSelectData(linkagedTaget, {[linkagedTaget.linkageMoreParamKey]: target,});}if (linkageKeyList) {finallyLinkageSolve(targetItem);}emit("searchChange", data.formInline);
};//船舶白名单预警类型的控制逻辑
const checkAll = ref(true);
const isIndeterminate = ref(false);
const handleCheckAllChange = (val, formItemKey) => {data.formInline[formItemKey] = val ? data.checkedAll : [];isIndeterminate.value = false;
};
const handleCheckedChange = (value) => {const checkedCount = value.length;checkAll.value = checkedCount === data.checkedAll.length;isIndeterminate.value =checkedCount > 0 && checkedCount < data.checkedAll.length;
};
// 最终联动逻辑解决方案
const finallyLinkageSolve = async (targetItem) => {if (!targetItem.linkageKeyList?.length) return;const targetLinkItems = props.formItems.filter((aitem) =>targetItem.linkageKeyList.includes(aitem.key));if (targetItem.linkageAction) {if (targetItem.linkOpenSetTimeout) {setTimeout(() => {targetItem.linkageAction(data.formInline[targetItem.key],targetLinkItems,targetItem.optionsData,data.formInline);}, 500);} else {let value =data.formInline[targetItem.key] || data.formInline[targetItem.key] == 0? data.formInline[targetItem.key]: props.formItemsVal[targetItem.key];targetItem.linkageAction(value, targetLinkItems, targetItem.optionsData);}}
};
const drawTypeChange = () => {emit("drawTypeChange", data.formInline.drawType);
};
const validateForm = async () => {let result = true;await ruleAreaFormRef.value.validate((valid, fields) => {const coordinateTarget = props.formItems.find((item) => item.type === "coordinate");if (coordinateTarget && fields) {const fieldsKey = Object.keys(fields);if (fieldsKey.length === 1 && fieldsKey[0] === coordinateTarget.key) {if (coordinateTarget.rule?.[0].required) {for (let coorItem in data.coordinate) {if (!data.coordinate[coorItem]) {return (result = false);}}return (result = true);}}}return (result = valid);});let formObj = Object.assign({}, data.formInline);return {isValidate: result,formData: transformObject(formObj, ["cityValue", "drawType", "BufferArea"]),coordinate: data.coordinate,};
};
const resetForm = () => {ruleAreaFormRef.value.resetFields();
};
const getFormItems = () => {const formItemsKeys = props.formItems.map((aitem) => aitem.key).filter(Boolean);return formItemsKeys;
};
const getFromData = () => data.formInline;//切换预警类型的选择
const warningLevelChange = (val) => {if (val == 1) {data.bufferData.forEach((el) => {if (el.level > val && data.formInline[el.key] != "") {data.formInline[el.key] = "";}});}
};const getSelectData = async (selectOption, moreparams) => {const { resData } = await useAxios({url: selectOption.url,method: "post",param: { pageNo: 1, pageSize: 0, ...moreparams },});if (resData.data && resData.data.length > 0) {let seletData = resData.data.map((item) => {return {label: selectOption.optionParam && item[selectOption.optionParam.label],value:selectOption.optionParam &&selectOption.optionParam.value !== "itemsString"? item[selectOption.optionParam.value]: JSON.stringify(item),};});selectOption.optionsData = seletData;//下拉框需要设置默认值的if (selectOption.default) {data.formInline[selectOption.key] = selectOption.optionsData[0].value;if (selectOption.cablckData) {selectOption.cablckData(selectOption.optionsData);}} else {data.selectData = selectOption.optionsData;if (selectOption.all)selectOption.optionsData.unshift({ label: "全部", value: "" });}} else {selectOption.optionsData = [{ label: "暂无数据", value: "" }];}
};
const getSelectTreeData = async (selectOption, moreparams) => {const { resData } = await useAxios({url: selectOption.url,method: selectOption.methed || "post",param: selectOption?.isNoGetParams? "": { pageNo: 1, pageSize: 10, ...moreparams },},selectOption.headers);const myModifyData = arrayToTreeRec({data: resData.data.filter((el) => el.type !== -1),pid: 0,idKey: "pid",pidKey: "parentId",});data.resTreeData = resData.data;data.treeData = myModifyData;
};
const getListData = async (selectOption, moreparams) => {const { resData } = await useAxios({url: selectOption.url,method: selectOption.methed || "post",param: selectOption?.isNoGetParams ? "" : { ...moreparams },},selectOption.headers);let _topData = [];const _temArr = resData.list ? resData.list : resData.data;let _data = _temArr.map((el) => {el.label = el.name;el.value = el.pid;el.parentId = 0;if (selectOption.isPinxixi) {if (!el.shipCnName) {el.nameAndShipName = el.name;_topData.push(el);} else {el.nameAndShipName = el.name + "【" + el.shipCnName + "】";}}return el;});const _data2 = _data.filter((el) => el.shipCnName);const _data3 = [..._topData, ..._data2];const myModifyData = arrayToTreeRec({data: selectOption.isPinxixi ? _data3 : _data,pid: 0,idKey: selectOption.isPinxixi ? "name" : "pid",pidKey: "parentId",});data.treeDataList = myModifyData;
};const gettreeLocationSelect = async (selectOption, moreparams) => {if (!store.areaList) {const { resData } = await useAxios({url: selectOption.url,method: selectOption.methed || "post",param: selectOption?.isNoGetParams ? "" : { ...moreparams },},selectOption.headers);const _data = resData.list.map((el) => {el.label = el.name;el.value = el.pid;el.parentId = 0;if (selectOption.isPinxixi) {el.nameAndShipName = el.name + "【" + el.shipCnName + "】";}return el;});const myModifyData = arrayToTreeRec({data: _data,pid: 0,idKey: "pid",pidKey: "parentId",});data.treeLocationSelect = myModifyData;} else {const myModifyData = arrayToTreeRec({data: store.areaList.filter((el) => el.type !== -1),pid: 0,idKey: "pid",pidKey: "parentId",});data.treeLocationSelect = myModifyData;data.storeTrseeData = myModifyData;}
};
//切换省市地址
const citySelectChange = (value) => {data.formInline["province"] = value[0];data.formInline["city"] = value[1];
};// 自定义el-select组件的filter-method使得其可以编辑内容
const handleSelectEdit = (filterVal, item) => {if (item.filterable) data.editSelectValue = filterVal;
};
const filtertreeLocationSelect = async (filterVal, item, type) => {if (!filterVal) return;data.remoteSelectLoading = true;if (item.type == 'treeLocationSelect') {const _keyParam = item.filterablePrama.keyParamconst moreparams = { [_keyParam]: filterVal, ...item.filterablePrama };delete moreparams.keyParamawait handleSubFilter(item, moreparams);data.remoteSelectLoading = false;}
};
const handleSubFilter = async (selectOption, moreparams) => {const { resData } = await useAxios({url: selectOption.url,method: selectOption.methed || "post",param: selectOption?.isNoGetParams ? "" : { ...moreparams },},selectOption.headers);let myModifyDataconst _listArr = resData.list ? resData.list : resData.data;if (selectOption.isTrss) {//四川省树状结构const _data = _listArr.map((el) => {el.label = el.name;el.value = el.pid;if (selectOption.isPinxixi) {el.nameAndShipName = el.name + "【" + el.shipCnName + "】";}return el;});myModifyData = arrayToTreeRec({data: _data.filter((el) => el.type !== -1),pid: 0,idKey: "pid",pidKey: "parentId",});} else {myModifyData = _listArr}data.treeLocationSelect = myModifyData;
};
// onMounted(() => {
//     getCtitysData();
//     mapData = props.MapData;
//     data.headerApi = { Authorization: store.userInfo.token }
// })
//获取区域所属省市
const getCtitysData = async () => {let requrl = "./json/city.json";let resData = await axios.get(requrl).then((res) => {return res.data.citiesData;});resData.map((item) => {item.name = item.province;return item;});data.citiesData = resData;
};
const setCheckBoxData = (item) => {setTimeout(() => {data.formInline[item.key] = item.optionCheckAll? ["0", ...item.optionsData.reduce((pre, cre) => [...pre, cre.value], [])]: [];data.checkedAll = data.formInline[item.key];}, 0);checkAll.value = true;isIndeterminate.value = false;
};//从服务器搜索下拉框内容
const remoteMethod = (query, selectItem) => {debounce(async () => {if (!query) return;data.remoteSelectLoading = true;const { resData } = await useAxios({url: selectItem.url,method: "post",param: { [selectItem.searchKey]: query },},selectItem.headers);const finalListData = selectItem.handleSpecialData? selectItem.handleSpecialData(resData.data): resData.data;// data.selectDataAllInfo = finalListData;if (finalListData.length) {data.remoteSelectData = finalListData.map((item) => {if (selectItem.labelMulti)return {label:item[selectItem.optionParam.label]?.trim() ||item[selectItem.optionParam.otherlable]?.trim(),value: item[selectItem.optionParam.value],itemInfo: {...selectItem.labelMulti,addDataInfo: item,},};return {label:item[selectItem.optionParam.label]?.trim() ||item[selectItem.optionParam.otherlable]?.trim(),value: item[selectItem.optionParam.value],itemInfo: JSON.stringify(item),};});} else {//避免重复插入多个let isAdd = data.remoteSelectData.filter((item) => item.value == query);if (!isAdd.length) {data.remoteSelectData.unshift({ label: query, value: query });}}data.remoteSelectLoading = false;setTimeout(() => {data.remoteSelectLoading = false;}, 1000);}, 500)();
};
const getRemoteSelect = async (selectOption, moreparams) => {if (props.dialogType == "edit") {selectOption.pageInfo = {[selectOption.searchKey]: props.formItemsVal[selectOption.searchKey],};}const { resData } = await useAxios({url: selectOption.url,method: "post",param: selectOption.pageInfo ?? { pageNo: 1, pageSize: 0, ...moreparams },},selectOption.headers);const finalListData = selectOption.handleSpecialData? selectOption.handleSpecialData(resData.data): resData.data;// data.selectDataAllInfo = finalListData;if (finalListData.length) {data.remoteSelectData = finalListData.map((item) => {if (selectOption.labelMulti)return {label:item[selectOption.optionParam.label]?.trim() ||item[selectOption.optionParam.otherlable]?.trim(),value: item[selectOption.optionParam.value],itemInfo: {...selectOption.labelMulti,addDataInfo: item,},};return {label:item[selectOption.optionParam.label]?.trim() ||item[selectOption.optionParam.otherlable]?.trim(),value: item[selectOption.optionParam.value],};});}
};const watchKeys = reactive([]);
watch(() => props.formItemsVal,(val) => {data.isAbled = false;if (val) {data.isAbled = true;data.formInline = {};data.formInline = Object.assign({}, val);}},{ immediate: true }
);
watch(() => props.formItems,(val) => {//构造需要动态显示的表单下拉项数据val.forEach((item) => {if (item.key) {//某些值是否需要监视if (item.watchChage) {watchKeys.push(item);}//!props.formItemsVal代表添加if (!props.formItemsVal) {data.formInline[item.key] =item.defaultValue !== undefined && item.defaultValue !== null? item.defaultValue: "";}if (item.type == "select") {if (item.optionsData.length == 0 && item.url) {// 动态获取下拉框内容getSelectData(item);} else if (item.defaultVal) {data.formInline[item.key] = item.defaultVal;} else if (item.defaultVal && !props.formItemsVal) {data.formInline[item.key] = item.defaultVal;}if (item.linkageKey) {if (props.formItemsVal) {data.formInline[item.key] = props.formItemsVal[item.key];searchChange(item.linkageKey,item.optionsData,data.formInline[item.key],item.linkageDraw);}}}if (item.type == "selectTree") {if (item.optionsData.length == 0 && item.url) {// 动态获取下拉框内容getSelectTreeData(item);}}if (item.type == "treeMuiltSelect") {if (item.optionsData.length == 0 && item.url) {data.tempObj = item;getListData(item, item.moreparams);} else {data.treeDataList = item.optionsData;}}if (item.type == "treeLocationSelect") {if (item.optionsData.length == 0 && item.url) {data.tempObj = item;gettreeLocationSelect(item, item.moreparams);}}if (item.type == "textarea" && item.defaultVal)props.dialogType !== "edit" &&(data.formInline[item.key] = item.defaultVal);if (item.type == "checkBox") {data.formInline[item.key] = [];//item.optionCheckAll==true,默认填充一个全部类型的值为0setCheckBoxData(item);}if (item.type == "remoteSelect") {getRemoteSelect(item);}if (item.rule) {merge(data.rules, { [item.key]: item.rule });}// 联动逻辑最终解决方案(优于之前的分散的联动逻辑)finallyLinkageSolve(item);}});},{immediate: true,}
);let instance = null; //绘制地理要素
let drawLayer = null; //绘制时临时创建的图层
let mapData = {};
//初始化绘制
const drawArea = () => {initDraw();drawLayer && drawLayer.getSource().clear();instance = mapDrawGraph(mapData.MapData,drawLayer,"Point",handlerDarwResult);
};
const initDraw = () => {let _Map = mapData;instance && _Map.MapData.GlobalMap.removeInteraction(instance);drawLayer = _Map._layer.creatTempLayer({layerName: "drawTempPoint",title: "绘制临时图层选点",zindex: 10,});
};
const handlerDarwResult = (drawResult) => {if (drawResult.coods.length !== 0) {let myCo = Object.assign({}, drawResult.coods);data.coordinate = myCo[0];for (let key in data.coordinate) {data.coordinate[key].indexOf("") >= 0 &&(data.coordinate[key] = data.coordinate[key].trim());}}instance = null;
};
const handleOpenDialog = (row, item) => {item.getRowInfo({ ...row, ...item, ...data.formInline });
};
const uploadRef = ref();
const handleResult = (state, info, item) => {if (state === "success") {const { data: resData } = info;const { address, fileName } = resData;const _fileName = !fileName? "附件名称" + resData.split("/")[resData.split("/").length - 1]: fileName;if (!fileName) {data.formInline[item.key] = resData;data.headerResult.fileName = resData;} else {data.formInline.fileName = _fileName;data.formInline.address = address;}item.getRowInfo({ ...resData, ...item, ...data.formInline });}ElMessage({type: state,message: `导入文件上传${state === "success" ? "成功" : "失败"}`,});
};
const fileClear = (state, info, item) => {if (state === "fileClear") {data.formInline[item.key] = "";const params = {fileName: info,fileType: item.option[0].uploadParames.fileType,};item.clearFunc(params);}
};
const uploadSingleImg = (state, info, item) => {if (state === "success") {const { data: resData } = info;item.getRowInfo(resData);upImgState.dialogImageUrl = BASEUrl + "/file/" + resData;const _fileList = data.formInline[item.key] || [];_fileList.unshift({ url: upImgState.dialogImageUrl });data.formInline[item.key] = _fileList;}ElMessage({type: state,message: `单个文件上传${state === "success" ? "成功" : "失败"}`,});
};
const beforeUploadSingleImg = (rawFile) => {if (!rawFile) return false;if (rawFile.type !== "image/jpeg" && rawFile.type !== "image/png") {ElMessage.error("文件类型须为图片格式!");return false;} else if (rawFile.size / 1024 / 1024 > 10) {ElMessage.error("文件大小须小于10MB!");return false;}return true;
};
const beforeRemoveSingleImg = (state, info, item) => {if (state === "remove") {let _fileName = "";if (!info.response) {_fileName = info.url.split("/")[info.url.split("/").length - 1];} else {_fileName =info.response.data.split("/")[info.response.data.split("/").length - 1];}const _fileType = item.option.uploadParames.fileType;item.removeImg({title: "删除图片",fileName: _fileName,fileType: _fileType,});data.formInline[item.key] = [];}return true;
};
const upImgState = reactive({dialogVisible: false, //预览弹框显示与否dialogImageUrl: "",fileList: [],
});
const handlePictureCardPreview = (file) => {upImgState.dialogImageUrl = file.url || BASEUrl + file.url;upImgState.dialogVisible = true;
};
const handlechange = (val, limit, isJump) => {if (isJump) {let _data = {};let _val = val;if (Array.isArray(val)) {_val = _val[_val.length - 1];}_data = data.resTreeData.find((item) => item.pid == _val);if (!_data) return;locationPoint(_data.geom);}if (!limit) return;if (limit == "有联动") {getListData(data.tempObj, {...data.tempObj.moreparams,areaIdCondition: val,});}if (limit == "有联动2") {getListData(data.tempObj, {organization: val,});}
};
const handleSelectchange = (val, item) => {const _findObj = store.areaList.find((el) => el.pid == val[val.length - 1]);if (_findObj) {const isOk =Array.isArray(_findObj.ferryPortAreaVos) &&_findObj.ferryPortAreaVos.length > 0;if (!isOk) {data.formInline[item.key] = data.formInline[item.key].filter((el) => {return el !== val[val.length - 1];});ElMessage.warning("该区域下暂无渡口!");}}
};
const blur = (item, type) => {if (item.type === "treeLocationSelect") {zeroSelectData();}
};
const zeroSelectData = () => {data.treeLocationSelect = data.storeTrseeData
}
defineExpose({validateForm,resetForm,getFormItems,getFromData,getListData,
});
</script><style lang="scss" scoped>
.area-from {display: flex;justify-content: space-between;flex-wrap: wrap;:deep(.el-form-item) {margin-right: 0px;// margin-bottom: 20px;max-width: 50%;.el-form-item__label {color: #fff;font-size: 16px;padding: 0px;padding-right: 10px;min-width: 100px;display: flex;justify-content: flex-end;align-items: center;line-height: 22px;}.el-form-item__error {white-space: nowrap;}.el-input__wrapper {background: rgba(26, 136, 198, 0.3);box-shadow: none;border: 1px solid #62a3ff;border-radius: unset;.el-input__inner {color: #fff;}.el-input__inner::placeholder {color: #d0eeff;}.el-input__suffix {color: #fff;}}.el-select__wrapper {background-color: #08387e;box-shadow: 0 0 0 1px #62a3ff inset;}.el-select__placeholder {color: #fff;}.el-radio__label {color: #fff;}.el-select .el-input__wrapper.is-focus {box-shadow: unset !important;}.el-input--suffix {color: #d0eeff !important;}.unit {color: #fff;margin-left: 5px;}.el-radio-group {min-width: 300px;}}.ship-white-warn {max-width: 100% !important;.warn-type {display: flex;align-items: center;:deep(.el-checkbox-group) {margin-left: 10px;}}}.select-area {width: 100%;>.el-form-item {width: 100%;max-width: 100%;margin-right: 0;}:deep(.select-trigger) {height: 100%;.el-input {height: 100%;}}:deep(.el-select__tags .el-tag--info) {background-color: rgb(16, 159, 204) !important;color: #ffffff;height: 30px;}:deep(.el-tag .el-tag__close) {color: #ffffff;}}.area-remark {// margin-top: 10px;width: 100%;>.el-form-item {width: 100%;max-width: 100%;margin-right: 0;.el-textarea {// width: 91%;:deep(.el-textarea__inner) {background-color: rgba(26, 136, 198, 0.3);border: 1px solid #62a3ff;border-radius: unset;outline: none;box-shadow: unset;color: #ffffff;&::placeholder {color: #d0eeff;}}}}}.warning-level {display: flex;justify-content: space-between;width: 100%;}.warning-distance {width: 100%;display: flex;justify-content: space-between;:deep(.el-form-item) {.el-form-item__content {flex-wrap: nowrap;}}}.cordinate-container {display: flex;align-items: center;:deep(.el-form-item) {max-width: 100%;margin-right: 0;.el-form-item__content {flex-wrap: nowrap;}}.wrapper {// width: 80%;background: rgba(26, 136, 198, 0.3) !important;border: 1px solid #62a3ff;padding: 6px 16px;display: flex;// flex-wrap: nowrap;.row-input-box {display: flex;align-items: center;&:first-child {margin-right: 22px;}.row-name {margin-right: 8px;white-space: nowrap;font-size: 14px;font-family: Microsoft YaHei-Regular, Microsoft YaHei;font-weight: 400;color: #d0eeff;line-height: 22px;}.input-item {display: flex;align-items: center;.inp-unit {margin: 0 6px;font-size: 12px;font-family: Microsoft YaHei-Regular, Microsoft YaHei;font-weight: 400;color: #52cbff;line-height: 19px;}.el-input {// width: 50px;:deep(.el-input__wrapper) {border: unset;border-radius: unset;background: #074665;padding: 1px;>input {text-align: center;}}}}}}.box {cursor: pointer;margin-left: 5px;display: inherit;align-items: inherit;}}.psw_home {padding-bottom: 15px;}.opration-box,.render-box {display: flex;justify-content: center;span {margin-right: 5px;}img {width: 16px;}}:deep(.el-input-group__append) {border-left: 0;border-top-left-radius: 0;border-bottom-left-radius: 0;box-shadow: 0 1px 0 0 #62a3ff inset, 0 -1px 0 0 #62a3ff inset,-1px 0 0 0 #62a3ff inset;background-color: #075480;padding: 0px 10px;background-color: #095680;}.avatar-uploader {width: 50px;height: 50px;display: flex;justify-content: center;align-items: center;border: 1px dashed #d9d9d9;img {width: 98%;height: 98%;object-fit: cover;}}
}
</style>
<style lang="scss">
.custom-header {.el-checkbox {display: flex;height: unset;}// .el-select-dropdown.is-multiple .el-select-dropdown__item.selected {//     color: #606266 !important;// }.el-select-dropdown.is-multiple .el-select-dropdown__item.selected::after {// background-color: rgb(47, 255, 127) !important;width: 25px;height: 25px;font-weight: bolder;font-size: 16px;}
}
</style>
调用组件AreaFormItem.vue的方式:
//调用组件
<template><AreaFormItemref="areaForm":formItems="formItems":formItemsVal="state.formItemsVal"/>
</template><script setup>
import { nextTick, onMounted, reactive, ref, watch } from "vue";
import AreaFormItem from "@/components/Form/AreaFormItem.vue";
const state = reactive({formItemsVal: {},
});
//备注:state.formItemsVal用于表单回显
const formItems = [{type: "datePicker",label: "签发日期",key: "dateOfIssue",rule: [{required: true,message: "签发日期不能为空!",trigger: "blur",},],},{type: "datePicker",label: "截止日期",key: "deadline",rule: [{required: true,message: "截止日期不能为空!",trigger: "blur",},],},{type: "select",label: "文件类型",key: "type",optionsData: [{label: "船舶经营许可证",value: 0,},{label: "船舶管理人许可证",value: 7,},],defaultVal: 0,rule: [{required: true,message: "文件类型不能为空!",trigger: "blur",},],},{type: "uploadSingleImg",label: "渡船证书",key: "file",option: {uploadParames: {fileType: 0, //渡船相关证书},img_bg: "table/upload.png",info: "upload",text: "上传",importUrl: BASEUrl + "/data/file/upload",},width: "100%",getRowInfo: (data) => {console.log("上传图片的结果", data);state.formItemsVal.file = data;},removeImg: (data) => {api.fileApi.deleteFile({ fileName: data.fileName, fileType: data.fileType }).then((res) => {if (res.status === 200 && res.data.code === 200) {ElMessage({type: "success",message: "删除成功",});}}).catch((err) => {console.log(err);});},rule: [{required: true,message: `${state.pageTheme}不能为空!`,trigger: "blur",},],},
];
<script>

 写到这儿就实现了表单组件的封装,根据调用组件传参的formItems变量的type类型渲染不同的表单组件例如:input、select等组件。。。最终随着项目的进行,表单组件的其他类型:

'location', 'medium','password', 'sexRadio', 'coordinate','radio','textarea','multipleSelect', 'uploadFile','uploadSingleImg',也会封装。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/91233.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/91233.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

flutter-完美解决键盘弹出遮挡输入框的问题

文章目录1. 前言2. 借助 Scaffold 的特性自动调整3. 使用 MediaQuery 精准控制抬升高度3.1. 底部抽屉内输入框的方案4. 注意事项5. 总结1. 前言 在 Flutter 的开发过程中&#xff0c;经常会碰到某一个页面有个 TextField 输入组件&#xff0c;点击的时候键盘会弹起来&#xff…

机器学习笔记(四)——聚类算法KNN、Kmeans、Dbscan

写在前面&#xff1a;写本系列(自用)的目的是回顾已经学过的知识、记录新学习的知识或是记录心得理解&#xff0c;方便自己以后快速复习&#xff0c;减少遗忘。概念部分大部分来自于机器学习菜鸟教程&#xff0c;公式部分也会参考机器学习书籍、阿里云天池。机器学习如果只啃概…

【C#】事务(进程 ID 64)与另一个进程被死锁在锁资源上,并且已被选作死锁牺牲品。请重新运行该事务。不能在具有唯一索引“XXX_Index”的对象“dbo.Test”中插入重复键的行。

&#x1f339;欢迎来到《小5讲堂》&#x1f339; &#x1f339;这是《C#》系列文章&#xff0c;每篇文章将以博主理解的角度展开讲解。&#x1f339; &#x1f339;温馨提示&#xff1a;博主能力有限&#xff0c;理解水平有限&#xff0c;若有不对之处望指正&#xff01;&#…

LeetCode Hot 100 搜索二维矩阵

给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a;每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。示例…

python毕设高分案例:基于机器学习的抑郁症数据分析与预测系统,flask框架,算法包括XGboost模型、梯度提升树模型等

1 绪论 1.1 课题研究背景和意义 1.1.1 研究背景 在医疗行业不断发展的当下&#xff0c;数据量呈现出爆炸式增长&#xff0c;医学数据的复杂性和多样性也达到了前所未有的程度。电子病历系统记录了患者丰富的诊疗信息&#xff0c;医学影像技术如 CT、MRI 等生成海量的图像数据…

STM32与ADS1256多通道数据采样原理及控制程序

好的,使用 STM32 与 ADS1256 通信读取多通道电压是精密数据采集的常见方案。ADS1256 是一款高精度、24 位、8 通道(或差分 4 通道)的 ΔΣ ADC,非常适合需要高分辨率的应用(如传感器信号、医疗仪器等)。 以下是对整个过程的详细分析及基于 STM32 HAL 库的程序示例: 核…

Spring Boot 3.5.x 使用 SpringDoc 2 / Swagger3

这篇文章资料来自于网络&#xff0c;对部分知识整理&#xff0c;这里只是记录一下&#xff0c;仅供参考 为什么要用 Swagger Swagger 的核心思想是通过定义和描述 API 的规范、结构和交互方式&#xff0c;以提高 API 的可读性、可靠性和易用性&#xff0c;同时降低 API 开发的难…

@RefreshScope 核心原理深度解析:Spring Boot 的动态魔法

让我们通过全新的原理图解和代码级分析&#xff0c;揭开RefreshScope实现配置热更新的神秘面纱&#xff01;一、工作原理全景图&#xff08;优化版&#xff09; #mermaid-svg-50lhLlOFeSRIWnLn {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px…

万字详解——OSI七层模型:网络通信的完整架构解析

OSI七层模型&#xff1a;网络通信的完整架构解析OSI&#xff08;Open Systems Interconnection&#xff09;七层模型是计算机网络领域最基础、最权威的参考框架。它由国际标准化组织&#xff08;ISO&#xff09;于1984年提出&#xff0c;旨在为不同厂商、不同技术的网络设备和系…

一个人开发一个App(OpenApi)

为了少写代码&#xff0c;统一前后端的网络层&#xff0c;我使用了OpenApi设计restful接口。然后用openapi-generator来生成flutter的代码。生成go代码用的是oapi-codegen,它对go更友好一些。 我们直接在api.yml中设计接口&#xff0c;所有的返回值与请求者都提取到components里…

光伏气象监测系统:助力光伏发电的智慧大脑

光伏气象监测系统&#xff1a;助力光伏发电的智慧大脑 柏峰【BF-GFQX】在全球积极推动能源转型、大力倡导 “双碳” 目标的当下&#xff0c;光伏发电凭借其清洁、可再生的显著优势&#xff0c;宛如一颗冉冉升起的新星&#xff0c;在能源领域迅速崭露头角&#xff0c;得以广泛推…

SpringCloud01——项目演变、微服务远程调用三种方式、springcloud介绍、nacos注册中心

目录 一、项目架构演变过程 1、单体应用架构 2、垂直应用架构 3、分布式服务架构 4、流动计算架构&#xff08;SOA架构&#xff09; 5、微服务架构 二、如何实现微服务远程调用 1、HttpClient工具类&#xff08;springboot中&#xff09; 形式1&#xff1a;调用第三方…

Oracle 和 MySQL 中的日期类型比较

Oracle 和 MySQL 都提供了多种日期和时间数据类型&#xff0c;但它们在实现和功能上有一些差异。以下是两者的主要日期类型对比&#xff1a;Oracle 日期类型DATE存储日期和时间&#xff08;精确到秒&#xff09;格式&#xff1a;YYYY-MM-DD HH24:MI:SS示例&#xff1a;TO_DATE(…

基于 Redis 实现共享 Session 登录的多种方法与实践

全文目录&#xff1a;开篇语**前言****1. 什么是共享 Session 登录&#xff1f;****2. 基于 Redis 实现共享 Session 的基本方法****2.1 通过 Redis 存储 Session 数据****2.1.1 基本流程****2.1.2 示例代码&#xff08;Java Spring Boot Redis&#xff09;****3. 使用 Redis…

spring cloud + easyRules 零基础搭建智能规则引擎

你是否曾想过在项目中嵌入一套轻量级且高度可扩展的规则引擎&#xff0c;轻松实现动态化的业务决策&#xff1f;在金融、电商、政务等领域&#xff0c;风险控制是业务安全的核心。传统硬编码方式很难应对复杂多变的风控需求&#xff0c;而规则引擎允许我们将这些规则独立出来&a…

AI应用:电路板设计

Diode Computers 公司 Diode Computers是一家专注于利用AI技术进行定制电路板设计和制造的公司&#xff0c;提供从概念到量产的全流程服务。其核心优势在于将电路板设计转化为AI可理解的代码形式&#xff0c;大幅提升设计效率并降低传统EDA工具的使用门槛 0。 核心服务 设计与制…

RocketMQ学习系列之——客户端消息确认机制

一、客户端使用MQ基本代码示例1、添加maven依赖<dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-client</artifactId><version>5.3.0</version> </dependency>2、生产者代码示例public class Produc…

[leetcode] 组合总和

39. 组合总和 - 力扣&#xff08;LeetCode&#xff09; i class Solution {int aim;vector<vector<int>> ret;vector<int> path; public:vector<vector<int>> combinationSum(vector<int>& nums, int target) {aim target;dfs(nums…

新能源行业B端极简设计:碳中和目标下的交互轻量化实践

新能源行业B端极简设计&#xff1a;碳中和目标下的交互轻量化实践内容摘要在新能源行业&#xff0c;碳中和目标正推动着企业追求更高的运营效率和更低的资源消耗。然而&#xff0c;传统的B端交互设计往往复杂繁琐&#xff0c;不仅增加了用户的操作成本&#xff0c;还可能导致资…

减速机:自动化生产线的“精密传动心脏”

减速机作为自动化生产线的核心传动部件&#xff0c;通过调节转速与扭矩实现设备精准控制&#xff0c;其在自动化生产线中发挥着关键作用。以下是其具体应用方式&#xff1a;输送线驱动在自动化生产线中&#xff0c;输送线用于运输物料、半成品或成品&#xff0c;通过减速机可以…