需求:用户在输入框输入多个条件时,可以对表格数据进行过滤查询,无需后端接口处理,利用了前端js里数组的filter方法进行过滤。
如下是效果图:
当用户在姓名的输入框里输入"张"后效果如下:
当用户在联系方式的输入框里输入"13"后效果如下:
当用户在身份证号的输入框里输入"4"后效果如下:
当用户清空姓名输入框里的"张"后效果如下:
当用户继续清空掉联系方式和身份证号后,就回到了我们最初的页面效果:
这个页面,获取表格数据是用了混入里的方法getTableData(pager, queryParams),分别传入页码和参数等,这里watch里立即监听了表格数据的变化,并对表格数据顺序前端做了处理,满足a.id == this.rowFormGet.docId的行排在最前面,对el-table自定义排序方法可以参考我之前发的文章《el-table自定义排序》。
然后三个输入框都用到了@input监听输入 @input=“querySearchAsync” ,只要这三个输入框有1个或1个以上输入框有输入东西那就走filterWay方法对表格进行过滤处理,否则就直接调接口刷新列表,这里用到了混入。下面分别是当前页面的代码和混入的代码:
<template>
<div>
<div style="margin:1rem 0;display: flex;">
<el-input
v-model.trim="queryParams.personName"
placeholder="请输入姓名"
style="margin-right:2rem"
@input="querySearchAsync"
clearable
@clear="getTableData(pager, queryParams)"
></el-input>
<el-input
v-model.trim="queryParams.personPhone"
placeholder="请输入联系方式"
style="margin-right:2rem"
@input="querySearchAsync"
clearable
@clear="getTableData(pager, queryParams)"
></el-input>
<el-input
v-model.trim="queryParams.card"
placeholder="请输入身份证号"
style="margin-right:2rem"
@input="querySearchAsync"
clearable
@clear="getTableData(pager, queryParams)"
></el-input>
</div>
<el-table
:data="tableDataShow"
:header-cell-style="{
background: ' #eff3fb',
color: '#3c4353',
'font-weight': 600
}"
border
style="width: 100%;"
>
<el-table-column prop="personName" label="姓名" align="center">
</el-table-column>
<el-table-column prop="personSex" label="性别" align="center">
<template slot-scope="scope">
{
{
scope.row.personSex == 1 ? "男" : "女" }}
</template>
</el-table-column>
<el-table-column prop="personPhone" label="联系方式" align="center">
</el-table-column>
<el-table-column prop="card" label="身份证号" align="center">
</el-table-column>
<el-table-column prop="personTypeName" label="人员类型" align="center">
</el-table-column>
<el-table-column prop="personTagName" label="标签" align="center">
</el-table-column>
<el-table-column fixed="right" label="操作" width="80" align="center">
<template slot-scope="scope">
<span
v-if="rowFormGet.docId && rowFormGet.docId == scope.row.id"
style="color:#aaaaaa"
>已选择</span
>
<span
style="color:#108ee9;cursor: pointer;"
@click="handleClick(scope.row)"
v-else
>选择</span
>
</template>
</el-table-column>
</el-table>
<div class="paginatBox">
<el-pagination
background
@size-change="changePageSize"
@current-change="changePage"
:current-page="pager.currentPage"
:page-sizes="[10, 20, 30, 40, 50]"
:page-size="100"
layout="total, sizes, prev, pager, next, jumper"
:total="pager.totalList"
>
</el-pagination>
</div>
</div>
</template>
<script>
import {
personGetList, formConnectDoc } from "@/api/resource.js";
import tableMixin from "@/views/tableMixin";
export default {
mixins: [tableMixin],
props: {
rowFormGet: {
type: Object,
default: {
}
}
},
data() {
return {
queryParams: {
personName: "",
personPhone: "",
card: ""
},
apiAddress: personGetList,
tableDataShow: []
};
},
watch: {
tableData: {
handler(newTable, oldTable) {
// console.log("table变化", newTable, oldTable);
let arr = JSON.parse(JSON.stringify(newTable));
if (Array.isArray(arr) && arr.length > 0) {
arr.sort((a, b) => {
if (
a.id == this.rowFormGet.docId &&
b.id != this.rowFormGet.docId
) {
return -1;
} else if (
a.id != this.rowFormGet.docId &&
b.id == this.rowFormGet.docId
) {
return 1;
} else {
return 0;
}
});
this.tableDataShow = arr;
// console.log("排序后的table", arr, this.tableDataShow);
}
},
immediate: true
}
},
methods: {
handleClick(row) {
this.$confirm(`确定将表单关联到${
row.personName}档案吗?`, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
let params = {
id: this.rowFormGet.id,
docId: row.id,
docType: "2"
};
formConnectDoc(params)
.then(res => {
this.$message({
type: "success",
message: "关联成功!"
});
this.$emit("myCancel");
})
.catch(err => {
});
})
.catch(() => {
});
},
querySearchAsync() {
let restaurants = JSON.parse(JSON.stringify(this.tableData));
if (
this.queryParams.personName ||
this.queryParams.personPhone ||
this.queryParams.card
) {
this.tableDataShow = this.filterWay(restaurants);
} else {
this.getTableData(this.pager, this.queryParams);
}
},
filterWay(restaurants) {
let filter = (condition, data) => {
return data.filter(item => {
return Object.keys(condition).every(key => {
return String(item[key])
.toLowerCase()
.includes(
String(condition[key])
.trim()
.toLowerCase()
);
});
});
};
//多条件过滤
let condition = {
personName: this.queryParams.personName,
personPhone: this.queryParams.personPhone,
card: this.queryParams.card
};
let newArr = filter(condition, restaurants);
return newArr;
}
}
};
</script>
<style lang="less" scoped>
.paginatBox {
width: 100%;
margin: 1.5rem auto;
}
</style>
//tableMixin.js
import {
initTableHeader } from '@/libs/initTools'
export default {
data() {
return {
// 按条件查询的查询参数
queryParams: {
},
// 表单的操作按钮
actionsBtns: {
position: 'right',
btns: [{
type: 'primary', text: '查询', action: 'submit' }],
},
// 表数据
tableData: [],
// 分页参数
pager: {
totalList: 0, currentPage: 1, pageSize: 10 },
pageSizeOpts: [10, 20, 30, 50],
// table的loading 效果
tableLoading: false,
}
},
computed: {
rememberPager() {
return {
currentPage: this.pager.currentPage,
pageSize: this.pager.pageSize,
}
},
},
methods: {
// 初始化表头样式
initTableHeader,
// 翻页
changePage(currentPage) {
this.pager.currentPage = currentPage
this.getTableData(this.pager, this.queryParams)
},
// 改变每页展示的数据条数
changePageSize(pageSize) {
this.pager.pageSize = pageSize
this.getTableData(this.pager, this.queryParams)
},
// 查询
handleQuery(params) {
this.queryParams = params
this.pager.currentPage = 1
this.getTableData(this.pager, this.queryParams)
},
// 获取table数据
getTableData(pager, queryParams) {
this.tableLoading = true
let myParams = {
pager: pager, condition: queryParams }
this.apiAddress(myParams)
.then((res) => {
const {
listpg, totalResult, showCount } = res.result
// table数据
listpg.forEach((item, index) => {
item.seriesNumber = index + 1
})
this.tableData = listpg
// 分页数据
this.pager.totalList = totalResult
this.pager.pageSize = showCount
this.tableLoading = false
})
.catch((e) => {
this.tableLoading = false
})
},
// 处理一些table的简单操作,如:删除、重置密码等
handleTableModalBtn(title, content, apiAddress, params) {
this.$Modal.confirm({
title: title,
content: content,
okText: '确定',
cancelText: '取消',
onOk: () => {
apiAddress(params).then((res) => {
this.$Message.success(res.message)
this.getTableData(this.pager, this.queryParams)
})
},
onCancel: () => {
this.$Message.info('您已取消该删除操作!')
},
})
},
// 导出表格数据
exportTableData(apiAddress, ids = [], queryParams, fileName) {
this.$Modal.confirm({
title: '导出表格数据',
content:
ids.length > 0
? '确定导出吗?'
: '提示:您尚未选中表格中的数据,您将导出所有信息',
onOk: () => {
apiAddress({
params: {
ids: ids.join(','), condition: queryParams },
fileName: fileName,
})
},
})
},
},
mounted() {
this.$nextTick(() => {
if (
this.$route.query.currentPage &&
this.$route.query.pageSize &&
!this.noPagerRem
) {
this.pager.currentPage = parseInt(this.$route.query.currentPage)
this.pager.pageSize = parseInt(this.$route.query.pageSize)
}
if (!this.isGetTable) {
this.getTableData(this.pager, this.queryParams)
}
})
},
}
//initTools.js
import {
validator } from '@/libs/validate'
/* 将参数从表单信息中抽取出来 */
const getFormParams = (formContent) => {
let formParams = {
}
formContent.forEach(item => {
if (item.params) {
formParams[item.params] = null
} else {
}
})
return formParams
}
/* 初始化表单验证规则 */
const initFormRules = (formContent) => {
let formRulesObj = {
}
formContent.forEach(item => {
formRulesObj[item.params] = []
if (item.required) {
formRulesObj[item.params].push({
required: item.required ? item.required : false,
message: `请输入${
item.label}`,
trigger: item.trigger ? item.trigger : 'blur',
type: item.validType && item.validType
})
}
if (item.validator && item.validator.length > 0) {
item.validator.forEach(validItem => {
formRulesObj[item.params].push({
validator: validator[validItem],
trigger: item.trigger ? item.trigger : 'blur'
})
})
}
})
return formRulesObj
}
/* 初始化表头 */
const initTableHeader = (tableHeadArr) => {
let tableHead = []
tableHeadArr.map(item => {
if (item.type) {
tableHead.push({
width: 60,
align: 'center',
type: item.type
})
} else if (item.slot) {
tableHead.push({
width: item.width ? item.width : 'auto',
minWidth: item.minWidth ? item.minWidth : 80,
align: item.align ? item.align : 'left',
title: item.title ? item.title : '',
key: item.key ? item.key : '',
slot: item.slot ? item.slot : '',
fixed: item.fixed ? item.fixed : ''
})
} else {
tableHead.push({
width: item.width ? item.width : 'auto',
minWidth: item.minWidth ? item.minWidth : 80,
align: item.align ? item.align : 'left',
title: item.title ? item.title : '',
key: item.key ? item.key : '',
slot: item.slot ? item.slot : '',
fixed: item.fixed ? item.fixed : '',
render: (h, params) => {
if (params.row[item.key] === '' || params.row[item.key] === null) {
return h('div', {
}, '-')
} else {
return h('div', {
}, params.row[item.key])
}
}
})
}
})
return tableHead
}
/* 初始化日期 */
const initDate = (errorDate) => {
if (!errorDate) return errorDate
const d = new Date(errorDate)
const year = (`${
d.getFullYear()}`).padStart(4, '0')
const month = (`${
d.getMonth() + 1}`).padStart(2, '0')
const date = (`${
d.getDate()}`).padStart(2, '0')
return `${
year}-${
month}-${
date}`
}
/* 初始化日期(月,日) */
const initMonthDate = (errorDate) => {
if (!errorDate) return errorDate
const d = new Date(errorDate)
const month = (`${
d.getMonth() + 1}`).padStart(2, '0')
const date = (`${
d.getDate()}`).padStart(2, '0')
return `${
month}/${
date}`
}
/* 初始化日期 和 时间 */
const initDateTime = (errorDate) => {
if (!errorDate) return errorDate
const d = new Date(errorDate)
const year = (`${
d.getFullYear()}`).padStart(4, '0')
const month = (`${
d.getMonth() + 1}`).padStart(2, '0')
const date = (`${
d.getDate()}`).padStart(2, '0')
const hour = (`${
d.getHours()}`).padStart(2, '0')
const minute = (`${
d.getMinutes()}`).padStart(2, '0')
const second = (`${
d.getSeconds()}`).padStart(2, '0')
return `${
year}-${
month}-${
date} ${
hour}:${
minute}:${
second}`
}
// 获取当前时间
function showTime () {
let now = new Date()
let year = now.getFullYear()
let month = String(now.getMonth() + 1).padStart(2, '0')
let date = String(now.getDate()).padStart(2, '0')
let hour = String(now.getHours()).padStart(2, '0')
let minutes = String(now.getMinutes()).padStart(2, '0')
let second = String(now.getSeconds()).padStart(2, '0')
let nowTime = year + '-' + month + '-' + date + ' ' + hour + ':' + minutes + ':' + '' + second
return nowTime
}
// 获取当前时分秒
function showMinutesAndSecond () {
let now = new Date()
let hour = String(now.getHours()).padStart(2, '0')
let minutes = String(now.getMinutes()).padStart(2, '0')
let second = String(now.getSeconds()).padStart(2, '0')
return hour + ':' + minutes + ':' + second
}
/**
* 获取当月的第几周
* a = d = 当前日期
* b = 6 - w = 当前周的还有几天过完(不算今天)
* a + b 的和在除以7 就是当天是当前月份的第几周
*/
function getMonthWeek (a, b, c) {
var date = new Date(a, parseInt(b) - 1, c); var w = date.getDay(); var d = date.getDate()
return Math.ceil(
(d + 6 - w) / 7
)
};
/**
* 获取选择当前的第几周,当前的周一、周日
* time 选择日期的时间戳
* {params} getNowDateAndNowWeek(new Date('2019-7-25').getTime())
*/
function getNowDateAndNowWeek (time) {
// 选中的时间戳
var timestamp = time
var serverDate = new Date(time)
// 本周周日的的时间
var sundayTiem = timestamp + ((7 - serverDate.getDay()) * 24 * 60 * 60 * 1000)
var SundayData = new Date(sundayTiem)
// 年
var tomorrowY = SundayData.getFullYear()
// 月
var tomorrowM = (SundayData.getMonth() + 1 < 10 ? '0' + (SundayData.getMonth() + 1) : SundayData.getMonth() + 1)
// 日
var tomorrowD = SundayData.getDate() < 10 ? '0' + SundayData.getDate() : SundayData.getDate()
// console.log('周日: ' + tomorrowY + '-' + tomorrowM + '-' + tomorrowD)
// 本周周一的时间
var mondayTime = timestamp - ((serverDate.getDay() - 1) * 24 * 60 * 60 * 1000)
var mondayData = new Date(mondayTime)
// 年
var mondayY = mondayData.getFullYear()
// 月
var mondayM = (mondayData.getMonth() + 1 < 10 ? '0' + (mondayData.getMonth() + 1) : mondayData.getMonth() + 1)
// 日
var mondayD = mondayData.getDate() < 10 ? '0' + mondayData.getDate() : mondayData.getDate()
var nowWeek = getMonthWeek(tomorrowY, tomorrowM, tomorrowD)
// 输出值
var config = {
SunDay: tomorrowY + '/' + tomorrowM + '/' + tomorrowD,
Monday: mondayY + '/' + mondayM + '/' + mondayD,
nowWeek: nowWeek
}
return config
}
// 用递归将树形数据转成列表数据
const transTreeToList = (treeData, labelName, valueName, listContainer = []) => {
treeData.forEach(item => {
listContainer.push({
label: item[labelName],
value: item[valueName]
})
if (item.children) {
transTreeToList(item.children, labelName, valueName, listContainer)
}
})
return listContainer
}
//
const store = {
debug: true,
state: {
message: 'xiaoming'
},
setMessage (value) {
if (this.debug) {
this.state.message = value
}
},
clearMessage (value) {
if (this.debug) {
this.state.message = ''
}
}
}
export {
getFormParams,
initFormRules,
initTableHeader,
initDate,
initMonthDate,
initDateTime,
transTreeToList,
store,
showTime,
showMinutesAndSecond,
getNowDateAndNowWeek
}
//validate.js
const validator = {
// 身份证号验证
idCard: (rule, value, callback) => {
const city = {
11: '北京',
12: '天津',
13: '河北',
14: '山西',
15: '内蒙古',
21: '辽宁',
22: '吉林',
23: '黑龙江 ',
31: '上海',
32: '江苏',
33: '浙江',
34: '安徽',
35: '福建',
36: '江西',
37: '山东',
41: '河南',
42: '湖北 ',
43: '湖南',
44: '广东',
45: '广西',
46: '海南',
50: '重庆',
51: '四川',
52: '贵州',
53: '云南',
54: '西藏 ',
61: '陕西',
62: '甘肃',
63: '青海',
64: '宁夏',
65: '新疆',
71: '台湾',
81: '香港',
82: '澳门',
91: '国外 '
}
let pass = true
if (!value || !/^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(value)) {
pass = false
} else if (!city[value.substr(0, 2)]) {
pass = false
} else {
pass = true
// 18位身份证需要验证最后一位校验位
// if (value.length === 18) {
// value = value.split('')
// // ∑(ai×Wi)(mod 11)
// // 加权因子
// const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
// // 校验位
// const parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2]
// let sum = 0
// let ai = 0
// let wi = 0
// for (let i = 0; i < 17; i++) {
// ai = value[i]
// wi = factor[i]
// sum += ai * wi
// }
// // var last = parity[sum % 11]
// if (parity[sum % 11] !== value[17]) { // 校验第十八位
// pass = false
// }
// }
}
!pass && callback(new Error('请输入正确的身份证号'))
pass && callback()
},
// 手机号验证
mp: (rule, value, callback) => {
if (value) {
if (!/^1[3,4,5,7,8,9]{1}[0-9]{9}$/.test(value)) {
/* 手机号验证 */
return callback(new Error('请输入正确的手机号'))
} else {
callback()
}
} else {
callback()
}
},
// 密码验证
pw: (rule, value, callback) => {
if (value) {
if (!/\w{6,16}$/.test(value)) {
/* 8到16位密码验证 */
return callback(new Error('请输入6到16位密码'))
} else {
callback()
}
} else {
callback()
}
},
// 邮箱验证
email: (rule, value, callback) => {
if (value) {
if (!/^\w+@\w+(\.[a-zA-Z]{2,3}){1,2}$/.test(value)) {
/* 邮箱验证 */
return callback(new Error('请输入正确的邮箱'))
} else {
callback()
}
} else {
callback()
}
},
// 数字验证
isNumber: (rule, value, callback) => {
if (value) {
if (!Number.isInteger(+value)) {
callback(new Error('请输入数字'))
} else {
callback()
}
} else {
callback()
}
},
// 最小长度为6
psLength: (rule, value, callback) => {
if (value) {
if (!(value >= 6 && value <= 30)) {
callback(new Error('请输入长度为6-30'))
} else {
callback()
}
} else {
callback()
}
},
// 审核意见最大长度为50
opinionLength: (rule, value, callback) => {
if (value) {
if (!(value.length <= 50)) {
callback(new Error('输入长度小于50字'))
} else {
callback()
}
} else {
callback()
}
},
// 验证 0 - 100 之间的整数
isNumberTo100: (rule, value, callback) => {
if (value) {
if (!/^[1-9][0-9]$|^[0-9]$|^100$/.test(value)) {
callback(new Error('请输入0-100之间的数字'))
} else {
callback()
}
} else {
callback()
}
},
// 不含中文
notChinese: (rule, value, callback) => {
if (value) {
if (/[\u4E00-\u9FA5]/g.test(value)) {
callback(new Error('不能包含中文'))
} else {
callback()
}
} else {
callback()
}
},
// IP
ip (rule, value, callback) {
if (value) {
// if (!(/(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})(\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})){3}/g.test(value))) {
if (!(/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(value))) {
return callback(new Error('IP格式不正确!'))
} else {
callback()
}
} else {
callback()
}
},
// 端口
port (rule, value, callback) {
if (value) {
if (!(/^([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-4]\d{4}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$/.test(value))) {
return callback(new Error('端口格式不正确!'))
} else {
callback()
}
} else {
callback()
}
},
// 验证 ssh端口
sshPort (rule, value, callback) {
if (value) {
if (!Number.isInteger(Number(value)) || (Number(value) < 0 || Number(value) > 65535)) {
callback(new Error('请输入0-65535之间的整数'))
} else {
callback()
}
} else {
callback()
}
},
// MAC地址
mac (rule, value, callback) {
if (value) {
if (!(/(([a-f0-9]{2}:)|([a-f0-9]{2}-)){5}[a-f0-9]{2}/gi.test(value))) {
return callback(new Error('MAC地址格式不正确!'))
} else {
callback()
}
} else {
callback()
}
},
// 验证时间是否大于当前时间
timeComparison (rule, value, callback) {
if (value) {
if (new Date(value).getTime() < new Date().getTime()) {
return callback(new Error('不能选择过去时间!'))
} else {
callback()
}
} else {
callback()
}
},
// 验证文件路径
filePath (rule, value, callback) {
if (value) {
if (!(/^[a-zA-Z]:\\[a-zA-Z_0-9\\]*/.test(value) || /^\/([/w]+\/?)+$/i.test(value))) {
return callback(new Error('请输入正确的文件路径!'))
} else {
callback()
}
} else {
callback()
}
},
// 排除非法字符输入 illegal character
ic (rule, value, callback) {
if (value) {
if ((/[@#$%^&*]+/g.test(value))) {
return callback(new Error('非法字符输入!'))
} else {
callback()
}
} else {
callback()
}
}
}
export {
validator
}