vue3中,封装el-select选择器组件(一)——表单四等分布局、查询、重置resetFields、el-date-picker起止日期、特殊字符校验、自定义指令v-throttle用于按钮防抖
vue3中,封装el-select选择器组件(一)——表单四等分布局、查询、重置resetFields、el-date-picker起止日期、特殊字符校验、自定义指令v-throttle用于按钮防抖
效果
1-流程状态
2-牵头单位
3-系统内单位角色
页面文件
index.vue
<template>
<div class="main-content">
<el-form
ref="formRef"
class="inline-form"
label-position="right"
label-width="130px"
:model="formInline"
>
<el-form-item class="width25" label="项目名称:" prop="prjName">
<el-input
v-model="formInline.prjName"
maxlength="100"
placeholder="请输入"
@input="(e) => (formInline.prjName = replaceCommonText(e))"
/>
</el-form-item>
<el-form-item class="width25" label="开始时间:">
<el-date-picker
v-model="prjDate"
end-placeholder="结束日期"
format="YYYY-MM-DD"
placeholder="请选择"
range-separator="至"
start-placeholder="开始日期"
type="daterange"
value-format="YYYY-MM-DD"
/>
</el-form-item>
<el-form-item class="width25" label="牵头单位:" prop="leadUnit">
<unitSelect
v-model="formInline.leadUnit"
v-model:contrUnitName="formInline.leadUnitName"
@change-unit="handleUnitChange"
/>
</el-form-item>
<el-form-item class="width25" label="系统内单位角色:" prop="innerRole">
<dictSelect v-model="formInline.innerRole" :dictid="'sgCompRole'" />
</el-form-item>
<el-form-item class="width25" label="流程状态:" prop="processState">
<dictSelect
v-model="formInline.processState"
:dictid="'projectExamine'"
/>
</el-form-item>
<el-form-item class="search_btn">
<el-button
v-throttle="3000"
type="primary"
@click="onSubmit(formInline)"
>
查询
</el-button>
<el-button
v-throttle="3000"
plain
type="primary"
@click="resetForm(formRef)"
>
重置
</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script setup>
import { queryByPage } from "@/api/project/couny";
import unitSelect from "@src/components/unitSelect";
import dictSelect from "@src/components/dictSelect";
import { replaceCommonText } from "@src/utils/validate";
const formRef = ref();
const prjDate = ref([]);
const formInline = ref({
prjName: "",
startDate: "", //项目开始日期
endDate: "", //项目结束日期
leadUnitName: "", //牵头单位
innerRole: "", //系统内单位角色
processState: "", //流程状态
});
const page = reactive({
pageSize: 10,
pageNumber: 1,
total: 0,
});
//重置-写法一
const resetForm = (formEl) => {
if (!formEl) return;
prjDate.value = [];
formEl.resetFields();
formInline.leadUnit = "";
onLoad();
};
//重置-写法二
// const resetForm = () => {
// formRef.value.resetFields()
// onLoad()
// }
//重置-写法三
// const resetForm = (formEl: FormInstance | undefined) => {
// if (!formEl) return
// formEl.resetFields()
// onLoad()
// }
//查询
const onSubmit = () => {
onLoad();
};
const onLoad = async () => {
const formData = {
pageSize: page.pageSize,
pageNumber: page.pageNumber,
...formInline,
startDate: prjDate.value ? prjDate.value[0] : "",
endDate: prjDate.value ? prjDate.value[1] : "",
};
await queryByPage(formData).then((res) => {
tableData.value = res.data.data;
page.pageSize = res.data.pageSize;
page.total = Number(res.data.total);
page.pageNumber = res.data.pageNumber;
});
};
const handleUnitChange = (val) => {
formInline.leadUnit = val.id;
formInline.leadUnitName = val.orgObjMdmName;
};
</script>
<style lang="scss" scoped></style>
公共样式
src\assets\css\element.css
.main-content {
padding: 20px 30px;
}
.inline-form {
overflow: hidden;
/* border-bottom: 1px dashed #ccc; */
}
.inline-form .search_btn{
float: right;
margin-right: 0 !important;
}
引用方法
src\app\science\api\project\couny.js
import request from '@src/utils/request'
import { sciencePostUrl } from '@/config'
//立项管理项目分页列表查询
export const queryByPage = (data) => {
return request({
url: `${sciencePostUrl}/prj/queryByPage`,
method: 'post',
data,
})
}
src\utils\validate.ts
// 禁止输入框特殊字符校验
export function replaceCommonText(e: any) {
if (!checkSpecificKeyWord(e)) {
// 提交关键字
ElMessage({
message: '不能包含关键词: ' + wordKey,
type: 'warning',
})
const y = e.replace(wordKey, '')
return y
} else {
const str = e.replace(
/[`~!@#$%^&*()_\-+=<>?:"{}|,./;'\\[\]·~!@#¥%……&*()——\-+={}|《》?:“”【 】、;,’。 ]/g,
''
)
const y = str.replace(/\s+/g, '')
return y
}
}
// 禁止输入框特殊字符校验-简约版
export function replaceSimpleText(e: any) {
if (!checkSpecificKeyWord(e)) {
// 提交关键字
ElMessage({
message: '不能包含关键词: ' + wordKey,
type: 'warning',
})
const y = e.replace(wordKey, '')
return y
} else {
const str = e.replace(
/[`~!@#$%^&*_\+=<>?:"{}|;'\\[\]·~!@#¥%……&*——\+={}|?:“”【 】;’。 ]/g,
''
)
const y = str.replace(/\s+/g, '')
return y
}
}
/**
* @description form表单特定字符校验
* @param value
* @returns {boolean}
*/
export function validateCommonText(rule: any, value: any, callback: any) {
const err: any = validatorSpecialCharacter(value)
if (err) {
callback(new Error(err.message))
return
}
callback()
}
// export function validateCommonText(rule: any, value: any, callback: any) {
// const noChars = "[`~!#$^&*\"()=|{}'‘: ; ',\\[\\].<>/?~!#¥……&*()——|{}【】‘;:”“'。,、?]‘'@ /% ‘"
// const v = value || ''
// for (let i = 0; i < noChars.length; i++) {
// const char = noChars[i]
// if (v.indexOf(char) != -1) {
// callback(new Error('不能使用特殊字符'))
// return
// }
// }
// const words = ['javascript', 'script', 'function', 'jscript', 'vbscript', 'confirm', 'onfocus', 'onblur', 'alert', 'location', 'document', 'window', 'onclick', 'href', 'prompt', 'onerror', '/*', 'data:', '\\u003e', '\\u003c', 'eval', 'url', 'expr', 'URLUnencoded', 'referrer', 'write', 'writeIn', 'body.innerHtml', 'execScript', 'setInterval', 'setTimeout', 'open', 'navigate', 'srcdoc', 'iframe', 'body', 'form', 'base', 'img', 'src', 'style', 'div', 'object', 'meta', 'link', 'input', 'comment', 'br', 'and', 'or', 'exec', 'insert', 'select', 'delete', 'update', 'alter', 'create', 'drop', 'count', 'chr', 'char', 'asc', 'mid', 'substring', 'master', 'truncate', 'declare', 'restore', 'backup', 'like', 'table', 'from', 'grant', 'use', 'column_name', 'group_concat', 'information_schema.columns', 'union', 'where', 'order', 'by', 'join', 'modify', 'into', 'substr', 'ascii', 'having']
// for (let i = 0; i < noChars.length; i++) {
// const word = words[i]
// if (v.indexOf(word) != -1) {
// callback(new Error('不能包含: ' + word))
// return
// }
// }
// callback()
// }
自定义指令
library\plugins\directive.ts
import type { DirectiveBinding } from 'vue'
export function setup(app: any) {
/**
* @description 自定义指令v-throttle
*/
app.directive('throttle', {
mounted(el: any, binding: DirectiveBinding) {
let { throttleTime } = binding.value
if (!throttleTime) {
throttleTime = 1000
}
let timer: any
let disable = false
el.addEventListener(
'click',
(event: any) => {
if (timer) {
clearTimeout(timer)
}
if (!disable) {
disable = true
} else {
event && event.stopImmediatePropagation()
}
timer = setTimeout(() => {
timer = null
disable = false
}, throttleTime)
},
true
)
},
})
}