vxe-table封装表头
待补充使用说明,但是可以用
- 一.效果
- 二.封装MyTable.vue
- 1.封装index.vue
- 2.日期选择筛选
- 3.输入筛选
- 4.下拉筛选
- 5.多选筛选
- 6.远程多选筛选
- 7.远程单选筛选
- 三、页面使用
- 1.具体页面使用
- 2.@/utils/filter.js
注意:需要使用jsx、vxe-table、element-plus
一.效果
二.封装MyTable.vue
注意:6和7涉及远程获取下拉数据的接口,你们可能不适应,但可借鉴实现方式
注意:6和7涉及远程获取下拉数据的接口,你们可能不适应,但可借鉴实现方式
注意:6和7涉及远程获取下拉数据的接口,你们可能不适应,但可借鉴实现方式
筛选图的图片自己随意搞两个即可
注意:import { queryDropDownList } from "@/api/service.js" // 使用页当前列key下拉如果是传递空数组selectList: [],需要使用该方法从后端获取下拉数据
1.封装index.vue
src/components/MyTable/index.vue
<template><div class="page-view flex-column" @click="handleClickOutside"><div style="width: 100%" class="flex-between" :class="[props.noPb ? '' : 'pb']"><div style="display: flex; color: #333; font-weight: 700"><slot name="titleContent"></slot></div><div style="display: flex"><el-button type="primary" plain @click="resetFilters">重置</el-button><slot name="btnContent"></slot><vxe-toolbar @click="clickToolbar" style="padding: 0 !important; height: 30px; margin-left: 10px" v-if="!tableData.hideCustom" ref="toolbarRef" custom></vxe-toolbar></div></div><slot name="pageAccount"></slot><div style="flex: 1; overflow-y: auto; scrollbar-gutter: stable"><!-- :key="keyIndex" --><vxe-gridref="xTable"v-bind="tableData":data="props.dataList"@checkbox-all="selectAllEvent"@checkbox-change="selectChangeEvent"@radio-change="radioChangeEvent"@sort-change="sortChangeEvent"><template v-for="(item, index) in tableData.columns" :key="index" v-slot:[`${item.field}`]="{ }"><div><div class="table-header-div"><span class="title-span"><my-tooltips :content="item.title ?? ''" /></span><!-- 控制筛选按钮显隐 --><template v-if="item.field !== 'actionBtn' && item.formType"><el-popover :visible="visible && item.field === showKey" :virtual-ref="refName" placement="bottom" :width="'fit-content'"><template #reference><!-- 两个筛选icon --><imgv-if="((searchData[item.field] || searchData[item.field] === 0) && !Array.isArray(searchData[item.field])) ||(Array.isArray(searchData[item.field]) && searchData[item.field].length > 0)":id="item.field"@click.stop="toggleNameFilter(item.field, item)"class="icon icon-span"src="./components/filterActive.png"/><img v-else :id="item.field" @click.stop="toggleNameFilter(item.field, item)" class="icon icon-span" src="./components/filterDefault.png" /></template><div @click.stop="() => {}"><div style="text-align: right"><el-button type="info" link @click="cancelFilter">重置</el-button><el-button type="primary" link @click="searchFilter">筛选</el-button></div><!-- 各类筛选组件 --><component:is="componentName[item.formType]"v-model="searchData[item.field]":list="item.selectList":type="item.formType":format="item.dateType":itemRow="item":requestApi="item.requestApi"@handleEnter="searchFilter"></component></div></el-popover></template></div></div></template><template #empty><jg-empty :type="emptyType" v-if="!loading" /></template></vxe-grid></div><!-- <pre>筛选和排序参数:{{ { ...searchData, ...sortJavaField } }}</pre></pre> --><!-- <pre>表格默认多列排序集合:{{ sortField }}</pre> --><!-- <pre>表格参数:{{ tableData }}</pre> --></div>
</template><script setup lang="jsx">
import { ref, watch, shallowRef, nextTick, onMounted, onBeforeUnmount } from "vue" // 按需引入ref函数
import { queryDropDownList } from "@/api/service.js" // 当前列下拉如果是传递空数组,需要使用该方法从后端获取下拉数据
import _ from "lodash"import InputFilter from "./components/input.vue"
import SelectFilter from "./components/select.vue"
import SelectRemoteFilter from "./components/selectRemote.vue"
import SelectMultipleFilter from "./components/selectMultiple.vue"
import SelectMultipleRemoteFilter from "./components/selectMultipleRemote.vue"
import DatePickerFilter from "./components/datePicker.vue"const componentName = ref({input: shallowRef(InputFilter),select: shallowRef(SelectFilter),selectRemote: shallowRef(SelectRemoteFilter),selectMultiple: shallowRef(SelectMultipleFilter),selectMultipleRemote: shallowRef(SelectMultipleRemoteFilter),daterange: shallowRef(DatePickerFilter),datetimerange: shallowRef(DatePickerFilter)
})defineOptions({name: "JgTable"
})const emit = defineEmits(["searchEvent", "checkboxEvent", "radioEvent", "updateSortChange"])const props = defineProps({tableDataObj: {type: Object,default: () => {return {}}},dataList: {type: Array,default: () => {return []}},emptyType: {type: String,default: "noResult"},// 是否展示展位图loading: {type: Boolean,default: false},noPb: {type: Boolean,default: false},
})let tableFlag = ref(false) //确保拿到父传子的表格数据再渲染
let keyIndex = ref(0) // 表格key
let tableData = ref({})
const toolbarRef = ref(null) // 工具栏
let xTable = ref(null) // 表格实例let searchData = ref({}) // 搜索参数 每个表头字段
// let sortObj = ref({}) // 单列排序
const sortField = ref({}) // 表格默认多列排序集合
const sortJavaField = ref({sortList: []
}) // 后端要的排序集合const showKey = ref(undefined) // 当前展示哪个筛选窗
const visible = ref(false) // 手动控制筛选窗显隐
const refName = ref(null) // 动态绑定在哪个表头图标下// 全局重置
const resetFilters = () => {for (const key in searchData.value) {if (Object.hasOwnProperty.call(searchData.value, key)) {searchData.value[key] = undefined}}visible.value = falseif (xTable.value) {xTable.value.clearCheckboxRow()}if (xTable.value) {xTable.value.clearRadioRow()}if (xTable.value) {xTable.value.clearSort()}sortField.value = {}sortJavaField.value.sortList = []// 因为无法通过element ui的api来清除排序样式,所以只能通过原生js来清除xTable.value.$el.querySelectorAll(".is-sortable").forEach(item => {// 移除table表头中的排序样式descending和ascendingitem.classList.remove("descending")item.classList.remove("ascending")}) // 清除多个排序// xTable.value.clearSort() // 清除单个排序getData()
}// 触发筛选
const toggleNameFilter = async (key, item) => {// console.log(key, item);if (_.isEmpty(item.selectList) && (item.formType === "selectMultiple" || item.formType === "select")) {await getJavaList(item) // 调用后端接口 获取下拉数据}// if (item.formType === 'selectMultipleRemote') {// await getJavaList() // 调用后端接口 获取下拉数据// }if (visible.value && showKey.value && showKey.value !== key) {visible.value = falsegetData()}refName.value = document.getElementById(key)showKey.value = keyvisible.value = !visible.value
}// 某些下拉数据 例如下拉大数据有500条 直接赋值会导致表格卡顿 通过点击表头再去接口获取数据赋值就不会影响表格的渲染
// (列里面数据回显使用后端给的中文,或者将javaList赋值给item的selectList)
let javaList = ref([])
const getJavaList = async item => {await queryDropDownList({fieldCode: item.field,...item.requestData}).then((res = []) => {// res = Array.from({ length: 200 }).map((ele, index) => {// return {// name: '下拉' + item.field + index,// value: index,// }// })javaList.value = res || []item.selectList = javaList.value || []}).finally(() => {})
}// 点击其他元素
const handleClickOutside = () => {// 且有筛选打开即去查询// if (visible.value) {// visible.value = false// // getData()// }
}// 重置
const cancelFilter = () => {searchData.value[showKey.value] = undefinedvisible.value = falsegetData()
}
// 筛选
const searchFilter = () => {visible.value = falsegetData()
}// 实时获取表头
const getRealData = () => {return { ...searchData.value, ...sortJavaField.value }
}
// 关闭表头弹框
// 点击其他元素
const handleCloseOutside = () => {// 且有筛选打开即去查询if (visible.value) {visible.value = false// getData()}
}
const getData = () => {console.log("筛选参数", { ...searchData.value, ...sortJavaField.value })emit("searchEvent", { ...searchData.value, ...sortJavaField.value })
}watch(() => props.dataList,() => {nextTick(() => {keyIndex.value++ // 原用来强制刷新列表渲染解决指令问题,后指令问题解决了。但强制刷新会触发表格重绘,导致排序效果消失和工具栏二次触发才有效,故不在使用强制刷新})},{ deep: true, immediate: false }
)
watch([() => props.tableDataObj],([tableDataObj]) => {// console.log('监听');tableFlag.value = false// console.log(tableDataObj)tableData.value = _.cloneDeep(tableDataObj) // 使用lodash的深拷贝方法// 表格全部增加hover效果tableData.value.rowConfig = { isHover: true }tableFlag.value = true// 判断空 也就是初次渲染时候需要排列出查询参数 后续数据变动不在初始化不在设置为undefined 否则会导致每次查询清空掉上次筛选条件// if (_.isEmpty(searchData.value)) {tableDataObj?.columns.forEach(ele => {if (ele.field) {searchData.value[ele.field] = ele.defaultValue || undefined}// 统一设置插槽头名称if (ele?.slots === undefined || ele?.slots === null || ele?.slots == {}) {ele.slots = {header: ele.field}}if (ele?.slots?.header === undefined || ele?.slots?.header === null) {ele.slots.header = ele.field}})// }},{ deep: true, immediate: true }
)// 多选
const selectAllEvent = () => {let val = xTable.value.getCheckboxRecords()emit("checkboxEvent", val)
}
const selectChangeEvent = () => {let val = xTable.value.getCheckboxRecords()emit("checkboxEvent", val)
}
// 清除所有行选中
const clearSelectEvent = () => {if (xTable.value) {xTable.value.clearCheckboxRow()}
}
// 单选事件
const radioChangeEvent = ({ row }) => {emit("radioEvent", row)
}
// 更新表格数据’
const updateTableDatas = data => {if (xTable.value) {xTable.value.loadData(data)}
}// 动态显隐列
const refreshColumns = () => {// console.log(field, isShow);if (xTable.value) {xTable.value.refreshColumn()}
}// 多列排序
const sortChangeEvent = ({ sortList }) => {// console.log(column, field, order, sortBy, sortList, $event)// console.log(sortList)sortJavaField.value.sortList = []sortJavaField.value.sortList = sortList.map(ele => {return {sortName: ele.field,sortType: ele.order === "desc" ? "DESC" : ele.order === "asc" ? "ASC" : undefined}})getData() // 直接统一在筛选里加入排序字段
}nextTick(() => {// 将表格和工具栏进行关联const $table = xTable.valueconst $toolbar = toolbarRef.valueif ($table && $toolbar) {$table.connect($toolbar)}
})
// 手动解决 因设置 :key 导致有概率不触发工具栏问题
const clickToolbar = () => {setTimeout(() => {// 将表格和工具栏进行关联const $table = xTable.valueconst $toolbar = toolbarRef.valueif ($table && $toolbar) {$table.connect($toolbar)}}, 100)
}const handleClickOther = () => {// 且有筛选打开即去查询if (visible.value) {visible.value = falsegetData()}
};// 在组件挂载时添加全局点击事件监听器
onMounted(() => {window.addEventListener('click', handleClickOther);
});// 在组件卸载时移除全局点击事件监听器
onBeforeUnmount(() => {window.removeEventListener('click', handleClickOther);
});defineExpose({clearSelectEvent,resetFilters,updateTableDatas,refreshColumns,getRealData,handleCloseOutside
})
</script><style lang="scss" scoped>
.page-view {height: 100%;width: 100%;
}.flex-start {display: flex;justify-content: flex-start;align-items: center;
}.flex-end {display: flex;justify-content: flex-end;
}.flex-column {display: flex;flex-direction: column;
}.flex-row {display: flex;flex-direction: row;
}.flex-between {display: flex;justify-content: space-between;align-items: center;
}.mr {margin-right: 16px;
}.ml {margin-left: 16px;
}.mt {margin-top: 12px;
}.mb {margin-bottom: 12px;
}.m0 {margin: 0;
}:deep(.vxe-grid) {thead {.vxe-cell {min-width: 64px;// padding-left: 0px !important;// 针对vxe-table4.7 结构修改↓display: flex;.vxe-cell--title {overflow: hidden;}.vxe-cell--sort-vertical-layout {width: 20px;}// 针对vxe-table4.7 结构修改↑}.table-header-div {display: flex;.title-span {min-width: 20px;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;word-break: break-all;// background-color: #1fff;// white-space: pre-wrap;}.icon-span {width: 20px;height: 20px;flex-shrink: 0;margin-top: 1px;margin-left: 5px;cursor: pointer;/* 防止缩小 *//* 给图标和标题之间添加一些间距 */}}}
}
</style>
2.日期选择筛选
src/components/MyTable/components/datePicker.vue
<template><el-date-pickerstyle="width: 360px"v-model="localValue":type="props.type"range-separator="~"start-placeholder="开始时间"end-placeholder="结束时间":format="props.format":default-time="defaultTime"@change="changeData($event, 'item.field', props.format)"/>
</template>
<script setup lang="jsx">
import { ref, watch } from "vue" // 按需引入ref函数
import _ from "lodash"
import dayjs from "dayjs"const emit = defineEmits(["update:modelValue"])defineOptions({name: "DatePicker"
})const props = defineProps({modelValue: {// 父组件 v-model 时数据没有指定参数名,所以此时属性modelValue会接收到v-model变量type: Array,default: () => {return []}},type: {type: String,default: () => {return "daterange"}},format: {type: String,default: () => {return "YYYY-MM-DD"}}
})const localValue = ref(props.modelValue || [])
const defaultTime = [new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)] // '12:00:00', '08:00:00'watch(() => props.modelValue,newValue => {localValue.value = newValue}
)// 时间格式化
const changeData = (value, key, dateType) => {// console.log(value, key, dateType);if (!_.isEmpty(value)) {localValue.value[0] = value[0] ? dayjs(value[0]).format(dateType) : ""localValue.value[1] = value[1] ? dayjs(value[1]).format(dateType) : ""} else {localValue.value = []}emit("update:modelValue", localValue.value)
}
</script>
3.输入筛选
src/components/MyTable/components/input.vue
<template><el-input v-model="localValue" placeholder="请输入" clearable style="margin-top: 10px; width: 150px" @change="handleChange" @keyup.enter="handleEnter" maxlength="100"/>
</template>
<script setup lang="jsx">
import { ref, watch } from "vue" // 按需引入ref函数const emit = defineEmits(["update:modelValue", "handleEnter"])defineOptions({name: "SelectMultipleFilter"
})const props = defineProps({modelValue: {type: String,default: () => {return undefined}}
})const localValue = ref(props.modelValue || undefined)watch(() => props.modelValue,newValue => {localValue.value = newValue}
)const handleChange = () => {emit("update:modelValue", localValue.value)
}
const handleEnter = () => {emit("handleEnter")
}
</script>
4.下拉筛选
src/components/MyTable/components/select.vue
<template><el-select filterable :reserve-keyword="false" v-model="localValue" placeholder="请选择" clearable style="margin-top: 10px; width: 160px" @change="handleChange" v-limit-length="100"><el-option v-for="item in list" :key="item" :value="item.value" :label="item.name" /></el-select>
</template>
<script setup lang="jsx">
import { ref, watch } from "vue" // 按需引入ref函数const emit = defineEmits(["update:modelValue"])defineOptions({name: "SelectMultipleFilter"
})const props = defineProps({modelValue: {type: [String, Number],default: () => {return undefined}},list: {type: Array,default: () => {return []}}
})const localValue = ref(props.modelValue || undefined)watch(() => props.modelValue,newValue => {localValue.value = newValue}
)const handleChange = () => {emit("update:modelValue", localValue.value)
}
</script>
5.多选筛选
src/components/MyTable/components/selectMultiple.vue
<template><el-select multiple collapse-tags filterable :reserve-keyword="false" v-model="localValue" placeholder="请选择" clearable style="margin-top: 10px; width: 160px" v-limit-length="100" @change="handleChange"><el-option v-for="item in list" :key="item" :value="item.value" :label="item.name" /></el-select>
</template>
<script setup lang="jsx">
import { ref, watch } from "vue" // 按需引入ref函数const emit = defineEmits(["update:modelValue"])defineOptions({name: "SelectMultipleFilter"
})const props = defineProps({modelValue: {type: Array,default: () => {return []}},list: {type: Array,default: () => {return []}}
})const localValue = ref(props.modelValue || [])watch(() => props.modelValue,newValue => {localValue.value = newValue}
)const handleChange = () => {emit("update:modelValue", localValue.value)
}
</script>
6.远程多选筛选
src/components/MyTable/components/selectMultipleRemote.vue
<template><el-selectmultiplecollapse-tagsfilterableremote:reserve-keyword="false":loading="listLoading"remote-show-suffix:remote-method="remoteMethod"v-model="localValue"placeholder="请搜索后选择"clearablestyle="margin-top: 10px; width: 160px"@change="handleChange"v-limit-length="100"><el-option v-for="item in javaList" :key="item" :value="item.value" :label="item.name" /></el-select>
</template>
<script setup lang="jsx">
import { ref, watch } from "vue" // 按需引入ref函数
// import { useList } from '@/service/index.js'
import { queryDropDownPage } from "@/api/service.js"const emit = defineEmits(["update:modelValue"])defineOptions({name: "SelectMultipleFilter"
})const props = defineProps({modelValue: {// 父组件 v-model 时数据没有指定参数名,所以此时属性modelValue会接收到v-model变量type: Array,default: () => {return []}},itemRow: {// 当前列对象type: Object,default: () => {return {}}},requestApi: {// 自定义筛选apitype: Function,default: null}
})const localValue = ref(props.modelValue || [])watch(() => props.modelValue,newValue => {localValue.value = newValue}
)// 某些下拉数据 例如下拉大数据有500条 直接赋值会导致表格卡顿 通过点击表头再去接口获取数据赋值就不会影响表格的渲染
// (列里面数据回显使用后端给的中文,或者将javaList赋值给item的selectList)
let javaList = ref([])
const listLoading = ref(false)
// 远程搜索接口获取下拉数据
const remoteMethod = query => {if (query) {listLoading.value = truelet api = props?.requestApi || queryDropDownPage // 自定义筛选事件和通用筛选事件api({pageNum: 1,pageSize: 100,searchKeyword: query,fieldCode: props.itemRow.field,...props.itemRow.requestData}).then((res = {}) => {// res = Array.from({ length: 100 }).map((ele, index) => {// return {// name: query + props.itemRow.field + index,// value: index,// }// })javaList.value = res?.records || []}).finally(() => {listLoading.value = false})} else {// javaList.value = []}
}const handleChange = () => {emit("update:modelValue", localValue.value)
}
</script>
7.远程单选筛选
src/components/MyTable/components/selectRemote.vue
<template><el-selectfilterableremote:reserve-keyword="false":loading="listLoading"remote-show-suffix:remote-method="remoteMethod"v-model="localValue"placeholder="请搜索后选择"clearablestyle="margin-top: 10px; width: 160px"@change="handleChange"v-limit-length="100"><el-option v-for="item in javaList" :key="item" :value="item.value" :label="item.name" /></el-select>
</template>
<script setup lang="jsx">
import { ref, watch } from "vue" // 按需引入ref函数
// import { useList } from '@/service/index.js'
import { queryDropDownPage } from "@/api/service.js"const emit = defineEmits(["update:modelValue"])defineOptions({name: "SelectMultipleFilter"
})const props = defineProps({modelValue: {// 父组件 v-model 时数据没有指定参数名,所以此时属性modelValue会接收到v-model变量type: [String, Number],default: () => {return undefined}},itemRow: {// 当前列对象type: Object,default: () => {return {}}}
})const localValue = ref(props.modelValue || undefined)watch(() => props.modelValue,newValue => {localValue.value = newValue}
)// 某些下拉数据 例如下拉大数据有500条 直接赋值会导致表格卡顿 通过点击表头再去接口获取数据赋值就不会影响表格的渲染
// (列里面数据回显使用后端给的中文,或者将javaList赋值给item的selectList)
let javaList = ref([])
const listLoading = ref(false)
// 远程搜索接口获取下拉数据
const remoteMethod = query => {if (query) {listLoading.value = truequeryDropDownPage({pageNum: 1,pageSize: 100,searchKeyword: query,fieldCode: props.itemRow.field,...props.itemRow.requestData}).then((res = {}) => {// res = Array.from({ length: 100 }).map((ele, index) => {// return {// name: query + props.itemRow.field + index,// value: index,// }// })javaList.value = res?.records || []}).finally(() => {listLoading.value = false})} else {// javaList.value = []}
}const handleChange = () => {emit("update:modelValue", localValue.value)
}
</script>
三、页面使用
1.具体页面使用
注意:其实只需要关注tableSetting这个配置式表格即可
<template><MyTable :tableDataObj="tableSetting" :dataList="tableData" @searchEvent="searchEvent" @checkboxEvent="checkboxEvent" @radioEvent="radioEvent"><template v-slot:titleContent><b>模板列表</b></template><template v-slot:btnContent><el-button :icon="CirclePlus" type="primary">右侧插槽内容</el-button></template></MyTable><my-pagination v-model:pageNum="queryForm.pageNum" v-model:pageSize="queryForm.pageSize" :totalNum="totalNum" @getList="getList"></my-pagination><!-- 编辑 --><el-dialog class="dialog-box" v-model="dialogItemObj.dialogVisible" :close-on-click-modal="false" :title="dialogItemObj.title" align-center width="720" style="min-height: 280px"><div style="height: 300px">弹框内容</div><!-- <FormInfo v-loading="formEditLoading" :formType="dialogItemObj.formType" :dataForm="dialogItemObj.dataForm" ref="formInfo"></FormInfo> --><template #footer><el-button @click="resetApplication()">取消</el-button><el-button type="primary" @click="submitApp()">提交</el-button></template></el-dialog>
</template><script setup lang="jsx">
defineOptions({name: 'Muban'
})
import { ref, onMounted, } from "vue"
import { CirclePlus } from '@element-plus/icons-vue'
// import { operateRuleConfig, delRuleConfig, } from "@/api/policyConfiguration.js" // 获取接口
let operateRuleConfig // 假设接口1
let delRuleConfig // 假设接口2
import { getDefaultValue, replaceStr, filters } from '@/utils/filter.js' // 表格查询参数处理
import { ElMessage, ElMessageBox } from "element-plus"
// import FormInfo from './components/formInfo.vue'const nameList = ref([]) // 下拉数据
const moreList = ref([{ name: '值1', value: 1 },{ name: '值2', value: 2 },
])
const tableSetting = ref({loading: false,size: 'small',showOverflow: 'tooltip',height: '100%',id: 'tableId_dataReport_01',// 唯一性idcustomConfig: {storage: true,checkMethod: ({ column }) => {return !['radio_key', 'seq_key', 'actionBtn'].includes(column.field)},}, // 自定义配置列radioConfig: {labelField: 'name',checkMethod: ({ row }) => {return row.jj !== 2}}, // 单选配置个别禁选择checkboxConfig: {labelField: 'name',checkMethod: ({ row }) => {return row.jj !== 2}}, // 多选配置个别禁选择sortConfig: { multiple: true, remote: true, chronological: false, }, // 多列排序columns: [{ type: 'radio', field: 'radio_key', width: 50 },{ type: 'checkbox', width: 50 },{ type: 'seq', field: 'seq_key', title: '序号', width: 50 },{ title: '长文本换行', field: 'aa', formType: 'input', sortable: true, showOverflow: false, minWidth: 90 },{ title: '省略号', field: 'bb', formType: 'input', sortable: true, showOverflowTooltip: true, width: 110 },{ title: '年月日', field: 'cc', formType: 'daterange', sortable: true, dateType: 'YYYY-MM-DD', width: 120 },{ title: '年月日时分秒', field: 'dd', formType: 'datetimerange', sortable: true, dateType: 'YYYY-MM-DD HH:mm:ss', width: 150 },{title: '单选', field: 'ee', formType: 'select', sortable: true, selectList: nameList, width: 100,slots: {default: ({ row }) => {const val = nameList.value.find(item => item.value === row.ee)?.name || ''return [<span>{val}</span>]},}},{title: '下拉多选', field: 'ff', formType: 'selectMultiple', sortable: true, selectList: [], requestData: { businessCode: '自定义接口参数' }, minWidth: 120,},{title: '遍历多选', field: 'faf', formType: 'selectMultiple', sortable: true, selectList: moreList.value, showOverflow: false, width:120,slots: {default: ({ row }) => {let dom = []let arr = row.faf || []arr.forEach(ele => {dom.push(<div style={{ height: '24px' }}>{filters(ele, moreList.value) || ''}</div>)})return dom},}},{title: '多选远程搜索', field: 'orgId', formType: 'selectMultipleRemote', selectList: [], requestData: { businessCode: 'DEVICE_TABLE' }, minWidth: 120,slots: {default: ({ row }) => {return [<span>中文名称{row.orgId}</span>]},}},{title: '点击事件', field: 'hh', formType: 'input', sortable: true, minWidth: 120,slots: {default: ({ row, column }) => {return [<span style="cursor: pointer;color:#11716f;text-decoration: underline;" onClick={() => clickItem(row, 'view', column)}> {row.hh} {column.field}</span>]},}},{title: '枚举', field: 'ii', formType: 'select', sortable: true, minWidth: 100, selectList: [{ name: '已反馈', value: 1 },{ name: '未反馈', value: 0 },],slots: {default: ({ row }) => (row ? <el-tag style="border: none;" class="cursor" type={row.ii === 1 ? 'primary' : 'warning'}>{row.ii === 1 ? '已反馈' : row.ii === 0 ? '未反馈' : ''}</el-tag> : ''),}},{title: '查询默认值', field: 'jj', formType: 'input', minWidth: 110, defaultValue: '123',},{title: '隐藏列', field: 'kk', minWidth: 100, visible: false,},{title: '操作', field: 'actionBtn', width: 160, fixed: 'right',slots: {default: ({ row }) => ([<el-button link type="primary" size="small" onClick={() => editItem(row, 'edit')} >编辑</el-button >,<el-divider direction="vertical" />,<el-button link type="primary" size="small" onClick={() => editItem(row, 'view')} >查看</el-button >,<el-divider direction="vertical" />,<el-button link type="danger" size="small" onClick={() => editItem(row, 'delete')} >删除</el-button >,])}},],
})let totalNum = ref(100)
let queryForm = ref({})
// 函数
const searchList = (item) => {console.log('%c【' + 'item' + '】打印', 'color: red;background:#0f0', item)
}
// 函数
const getList = (item) => {console.log('%c【' + 'item' + '】打印', 'color: red;background:#0f0', item)
}
let tableData = Array.from({ length: 10 }).map((ele, index) => {return {aa: '长文本换行' + index,bb: '长文本隐藏隐藏隐藏隐藏隐藏',cc: '2023-7-20',dd: '2023-7-20 10:10:10',ee: Math.floor(Math.random() * 5),ff: [1, 2],faf: [1, 2],gg: '中文',hh: Math.floor(Math.random() * 20),ii: Math.floor(Math.random() * 2),jj: index,kk: index,}
})let formEditLoading = ref(false) // 表单loading
// 上线申请表单
const formInfo = ref(null)
// 上线弹框显示
let dialogItemObj = ref({dialogVisible: false,title: '',dataForm: {},formType: 'add'
})
// 点击事件
const clickItem = (row, type, column) => {console.log(row, type, column);ElMessage({type: 'success',message: '点击',})
}
// 编辑或查看
const editItem = (row, type) => {dialogItemObj.value.formType = type// console.log(row, type); switch (type) {case 'edit':dialogItemObj.value.dialogVisible = truedialogItemObj.value.title = '编辑'dialogItemObj.value.dataForm = { ...row }break;case 'view':dialogItemObj.value.dialogVisible = truedialogItemObj.value.title = '查看'dialogItemObj.value.dataForm = { ...row }break;case 'delete':deleteItem(row, type)break;default:break;}
}
// 删除
const deleteItem = (row,) => {ElMessageBox.confirm("确定要删除该条数据信息吗?", "删除", {confirmButtonText: "确认",cancelButtonText: "取消",showClose: false,closeOnClickModal: false}).then(async () => {await delRuleConfig({ id: row.id })getList()ElMessage.success(`删除成功!`)})
}
// 创建应用申请
const submitApp = () => {let requestApi = operateRuleConfigformEditLoading.value = trueformInfo.value.getValidateData((data) => {// console.log('子组件返回参数', data);if (data) {requestApi({ ...data }).then(() => {let msg = dialogItemObj.value.formType === 'add' ? '新增成功' : '编辑成功'ElMessage.success(msg)dialogItemObj.value.dialogVisible = falsegetList()}).finally(() => {formEditLoading.value = false})} else {formEditLoading.value = false}})
}
// 清空
const resetApplication = () => {formInfo.value.resetForm(() => {dialogItemObj.value.dialogVisible = false})
}// 拿到搜索条件
const searchEvent = (data) => {let newList = replaceStr(['orgId',], ['orgIdList',], { ...queryForm.value, ...data })queryForm.value = newListsearchList()
}
// 多选
const checkboxEvent = (data) => {console.log('checkboxEvent', data);
}
// 单选
const radioEvent = (data) => {console.log('radioEvent', data);
}
onMounted(() => {setTimeout(() => {nameList.value = [{ name: '横向隔离', value: 0 },{ name: '纵向加密', value: 1 },{ name: '防火墙', value: 2 },{ name: '监测装置', value: 3 },{ name: '运维网关', value: 4 },{ name: '其他', value: 5 },]}, 1000);
})
</script><style lang="scss" scoped></style>
2.@/utils/filter.js
一般用不到这几个方法,我是特殊处理获取配置表单的默认值和接口传参处理key用的
// 下拉过滤回显
export const filters = (key, arr = []) => {const names = []const value = Array.isArray(key) ? key : [key]for (let i = 0; i < arr.length; i++) {if (value.includes(arr[i].value)) {names.push(arr[i].name)}}return names.join(";")
}// 拿到表格默认结构里的搜索默认值
export const getDefaultValue = columns => {let searchObj = {inputList: {},selectList: {},dateList: {}}columns.forEach(ele => {if (ele.field && ele.formType) {// if (ele.formType === 'input') {// searchObj['inputList'][ele.field] = ele.defaultValue || undefined// } else if (ele.formType === 'select' || ele.formType === 'selectMultiple' || ele.formType === 'selectMultipleRemote') {// searchObj['selectList'][ele.field] = ele.defaultValue || undefined// } else if (ele.formType === 'daterange' || ele.formType === 'datetimerange') {// searchObj['dateList'][ele.field] = ele.defaultValue || undefined// } else {// searchObj[ele.field] = ele.defaultValue || undefined// }searchObj[ele.field] = ele.defaultValue || undefined}})return searchObj
}// 拿到表头组件的搜索默认值
export const getSearchValue = (columns, data) => {let searchObj = {inputList: {},selectList: {},dateList: {}}columns.forEach(ele => {if (ele.field && ele.formType) {if (ele.formType === "input") {searchObj["inputList"][ele.field] = data[ele.field] || undefined} else if (ele.formType === "select" || ele.formType === "selectMultiple" || ele.formType === "selectMultipleRemote") {searchObj["selectList"][ele.field] = data[ele.field] || undefined} else if (ele.formType === "daterange" || ele.formType === "datetimerange") {searchObj["dateList"][ele.field] = data[ele.field] || undefined} else {searchObj[ele.field] = data[ele.field] || undefined}}})return searchObj
}// 暂时替换字段
export const replaceStr = (arr1, arr2, obj) => {// 创建一个新的对象,避免直接修改原始对象const newObj = { ...obj }// 遍历 arr1 并替换 newObj 中的相应属性名arr1.forEach((key, index) => {if (key in newObj) {// 用 arr2 中的对应值替换属性名newObj[arr2[index]] = newObj[key]// 删除旧的属性名delete newObj[key]}})return newObj
}
相关文章:
vxe-table封装表头
待补充使用说明,但是可以用 一.效果二.封装MyTable.vue1.封装index.vue2.日期选择筛选3.输入筛选4.下拉筛选5.多选筛选6.远程多选筛选7.远程单选筛选 三、页面使用1.具体页面使用2./utils/filter.js 注意:需要使用jsx、vxe-table、element-plus 一.效果 …...
力扣hot100 91-100记录
91-100 (动态规划) class Solution { public:int uniquePaths(int m, int n) {vector<vector<int>> f(m, vector<int>(n, 1));for(int i 1; i < m; i){for(int j 1; j < n; j){f[i][j] f[i-1][j] f[i][j-1];} }return f[…...
SpringMVC处理请求映射路径和接收参数
目录 springmvc处理请求映射路径 案例:访问 OrderController类的pirntUser方法报错:java.lang.IllegalStateException:映射不明确 核心错误信息 springmvc接收参数 一 ,常见的字符串和数字类型的参数接收方式 1.1 请求路径的…...
ESP32上C语言实现JSON对象的创建和解析
在ESP32上使用C语言实现JSON对象的创建和解析,同样可以借助cJSON库。ESP-IDF(Espressif IoT Development Framework)本身已经集成了cJSON库,你可以直接使用。以下是详细的步骤和示例代码。 1. 创建一个新的ESP-IDF项目 首先&…...
关于Qt对Html/CSS的支持
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、原生控件二、QtWebEngine总结 前言 最近遇到了一些问题需要使用Qt加载Html发现一些特性不能使用,估计很多人也和我一样遇到这种情况。需要说明…...
Python 读取 txt 文件详解 with ... open()
文章目录 1 概述1.1 注意事项1.2 模式说明1.3 文件准备 2 读文件2.1 读取整个文件2.2 逐行读取2.3 读取所有行到列表 3 写文件3.1 覆盖写入3.2 追加写入3.3 写入多行 4 实用技巧4.1 检查文件是否存在4.2 异常处理 1 概述 1.1 注意事项 文件编码:建议指定编码&…...
[Mac] 使用homebrew安装miniconda
使用虚拟环境可以对不同项目的依赖进行隔离。可以使用venv或者conda来创建和使用虚拟环境。 venv是Python内置的虚拟环境管理模块,适合纯Python项目以及快速轻量级的开发和部署。conda具备更强大的版本管理能力,但是占用较大的磁盘空间。 考虑到我基本不…...
如何获取适用于广告过滤增强的Chrome浏览器版本【广告净化】
不少人使用浏览器时,会遇到广告弹窗、视频前贴广告或页面跳转。这些情况会影响上网体验。想要改善,可以从选择合适版本的谷歌浏览器开始,并加上合理设置。 先打开电脑上的浏览器,在搜索栏中输入“谷歌浏览器官方下载页面”。找到带…...
JVM(Java虚拟机)详解
目录 1 JVM执行流程 2 JVM运行时数据区(内存布局) 2.1 堆 2.2 栈 2.3 方法区 2.4 程序计数器 2.5 Java和运行时数据区相关的异常 3 JVM类加载(Class Loading) 3.1 加载Loading 3.2 连接Linking 3.2.1 验证Verification…...
Vue3 + TypeScript,使用provide提供只读的响应式数据的详细分析与解决方法
原始无类型写法(不报错) typescript const applySampleTableData ref<ApplySample[]>([]); const applySampleListSymbol Symbol("applySampleList"); provide(applySampleListSymbol, readonly(applySampleTableData)); 类型推断&a…...
深入理解 BLE PHY 模式:1M、2M 与 Coded 的演进与应用
随着蓝牙技术不断演进,BLE(Bluetooth Low Energy)在物联网、可穿戴设备、智能家居等领域的应用愈发广泛。BLE 中的 PHY(Physical Layer,物理层)是决定无线传输速率、覆盖范围和功耗的核心因素。本文将以浅显易懂的语言,结合示意图和代码示例,系统梳理 BLE 三种 PHY 模式…...
人工智能与机器学习:二元分类决策树构建指南
引言 在人工智能与机器学习的领域里,算法犹如智慧的钥匙,开启着数据洞察的大门。决策树作为其中一颗璀璨的明珠,以其独特的非线性处理能力和可解释性备受瞩目。今天,让我们跟随作者的脚步,深入探究如何构建一个用于二…...
Ubuntu下软件运行常见异常退出问题汇总分析
软件在Ubuntu下运行时,可能会遇到各种异常退出情况,常见可分为以下几点: 目录 一、系统资源耗尽导致退出 二、权限导致无法运行 三、找不到依赖的动态库 四、编译可执行文件时,动态库所引用的头文件与动态库不匹配 一、系统资…...
机器学习漏洞大汇总——利用机器学习服务
在本节中,我们将展示机器学习框架中存在的漏洞,这些漏洞会直接处理模型工件,或者通过工件存储或模型注册表的凭证来处理。利用此类漏洞,攻击者可以在企业系统内部进行非常强大的横向移动,从而劫持被利用的模型注册表中的机器学习模型。 WANDB Weave 目录遍历 - CVE-2024-…...
类的六个默认成员函数
如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。 默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认…...
精益数据分析(21/126):剖析创业增长引擎与精益画布指标
精益数据分析(21/126):剖析创业增长引擎与精益画布指标 大家好!在创业和数据分析的探索道路上,我一直希望能和大家携手共进,共同学习。今天,我们继续深入研读《精益数据分析》,剖析…...
SAIL-RK3588协作机器人运动控制器技术方案
一、核心能力与政策适配 政策合规性 满足工信部《智能机器人重点技术攻关指南》要求,支持 EtherCAT主站协议(符合IEC 61158标准),助力企业申报工业机器人研发专项补贴(最高300万元/项目)核心板…...
手搓箱图并输出异常值(MATLAB)
看下需求 想要复刻这种箱图,咱们直接开始手搓 %% 可修改 % 生成模拟数据(假设5个用户群体的发帖数) data {randn(100,1)*10 30, ... % 核心用户randn(200,1)*5 10, ... % 边缘用户randn(150,1)*8 20, ... % 积极社交用户randn(8…...
Java:XML被自动转义
在Java中处理XML响应被自动转义的问题时,需结合XML规范及工具特性进行针对性处理。以下是常见原因及解决方案的总结: 一、XML自动转义的原因 字符安全性处理 XML中的保留字符(如 <、>、&)会被自动转义为实体&a…...
Day-3 应急响应实战
应急响应实战一:Web入侵与数据泄露分析 1. Web入侵核心原理 漏洞利用路径 未授权访问:弱口令(如空密码/默认口令)、目录遍历漏洞代码注入攻击:JSP/ASP木马、PHP一句话木马(利用eval($_POST[cmd])&…...
【软件设计师】模拟题一
以下是 10道软考-软件设计师模拟试题,涵盖高频考点和易错点,附带答案和解析: 一、软件工程 1. 在软件开发生命周期中,瀑布模型的主要特点是( ) A. 强调快速原型迭代 B. 阶段间有明…...
每日一练(4~24):互质的数【省模拟赛】
算法:暴力枚举 问题描述 如果两个整数 a, b 除了 1 以外,没有其它的公约数,则称整数 a 与 b 互质。 请问,与 2024 互质的数(包括 1)中,第 2024 小的是多少? 答案提交 这是一道结…...
金融软件测试有哪些注意事项?专业第三方软件测试服务机构分享
在现代金融行业中,软件系统的稳定性和安全性直接关系到资金的安全和业务的正常运转。金融软件因涉及庞大的资金流和敏感的个人及交易信息,对软件测试提出了更高的要求,那么金融软件在进行测试时有哪些注意事项呢?卓码软件测评作为专业的第三…...
关于QT信号、槽、槽函数的讲解
也是好久没有发帖子了,最近博主主要还是在边学QT边完成任务,所以进度很慢,但确实在这几天对于QT自身槽和信号这类特殊的机制有了一定简单的理解,所以还是想记录下来,如果有初学者看到帖子对他有一定的帮助,…...
算法训练营第三十天 | 动态规划 (三)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、01背包问题理论基础(一)动态规划五部曲确定dp数组以及下标的含义确定递推公式初始化dp数组确定遍历顺序 二、01背包问题理论基础&#…...
Vue开发网站会有“#”原因是前端路由使用了 Hash 模式
前言 网站链接中出现 #(井号)是因为你的前端路由使用了 Hash 模式(hash mode),这是一种前端框架(如 Vue.js、React 等)中常用的路由策略。 为什么有 # 比如 https://www.zimeinew.com/#/order…...
SpringBootTest报错
Unable to find a SpringBootConfiguration, you need to use ContextConfiguration or … 解决方案:在SpringTest注解中添加属性(classes )填写启动类 如我的启动类是MainApplication.class javax.websocket.server.ServerContainer no…...
【质量管理】现代TRIZ(萃智)理论概述
一、什么是TRIZ理论 TRIZ理论,即发明问题解决理论(Teoriya Resheniya Izobreatatelskikh Zadatch),是由前苏联发明家根里奇阿奇舒勒(Genrich S. Altshuller)于1946年创立的。它是一门基于知识的、面向人的发明问题解决系统化方法学。TRIZ理论通过研究大量的专利,总结出技…...
前端面经-JS篇(四)--回调地狱、promise异步编程、Proxy 与 Reflect 、模块化
一、回调地狱 回调地狱(Callback Hell),也称为回调地狱,是指在 JavaScript 中处理多个嵌套的异步回调函数时,代码结构变得非常难以阅读和维护的现象。 为什么会出现回调地狱? 回调地狱通常出现在需要执行…...
【oql】spark thriftserver内存溢出,使用oql查询导致oom的sql
eclipse memory analyzer (mat)软件内的OQL实现查询内促信息。 帮助信息:软件Help/Help Contents/Querying Heap Objects (OQL) 就是查询SparkExecuteStatementOperation 的statement 字段。 select objects s.statement from org.apache.spark.sql.hive.thriftser…...
算法设计与分析(基础)
问题列表 一、 算法的定义与特征,算法设计的基本步骤二、 算法分析的目的是什么?如何评价算法,如何度量算法的复杂性?三、 递归算法、分治法、贪婪法、动态规划法、回溯法的基本思想方法。四、 同一个问题,如TSP&#…...
爬虫学习——使用HTTP服务代理、redis使用、通过Scrapy实现分布式爬取
一、使用HTTP服务代理 由于网络环境、网站对用户的访问速度的限制等原因,使得爬取过程会出现IP被封禁,故使用代理可提高爬取速度。在Scrapy中提供了一个HttpProxyMiddleware专门用于进行爬虫代理设置。在使用该代理进行爬取操作时,需要先在ba…...
机器学习中的特征存储是什么?我需要一个吗?
本质上,特征存储是一个专用存储库,用于系统地存储和排列特征,主要用于数据科学家训练模型,并帮助已训练模型的应用程序进行预测。它是一个关键的聚合点,人们可以在此构建或修改从各种数据源提取的特征集合。此外,它还支持从这些特征组中创建和增强新的数据集,以满足处于…...
【C语言】C语言中的联合体与枚举类型
前言 在C语言中,联合体(union)和枚举(enum)是两种非常实用但又常被忽视的自定义数据类型。它们在内存管理、代码可读性以及程序设计的灵活性方面都有着独特的优势。今天,我们就来深入探讨一下联合体和枚举…...
Golang编程拒绝类型不安全
button-chen/containertypesafe-go: 使用泛型包装标准库的容器 list、ring、heap、sync.Pool 和 sync.Map,实现类型安全 简介 在 Go 中,标准库提供了多种容器类型,如 list、ring、heap、sync.Pool 和 sync.Map。然而,这些容器默认…...
炼锌废渣提取钴工艺流程
炼锌废渣中提取钴的工艺流程通常结合湿法冶金技术,针对废渣中钴与锌、铁、铜等金属的复杂共生特性,通过预处理、浸出、除杂、钴富集及提纯等步骤实现钴的高效回收。以下是典型工艺流程的详细说明: 一、预处理 炼锌废渣(如锌浸出…...
Restful接口学习
一、为什么RESTful接口是数据开发的核心枢纽? 在数据驱动的时代,RESTful接口如同数据高速公路上的收费站,承担着数据交换的核心职责。数据工程师每天需要面对: 异构系统间的数据交互(Hadoop集群 ↔ 业务系统…...
仿真每日一练 | ABAQUS应力松弛
应力松弛是弹性材料在应力作用下产生微塑性变形,并且逐渐积累,在保持应变或者位移不变的前提下,表现为应力逐渐下降的现象。今天介绍一个ABAQUS中应力松弛的相关案例,模型如下所示: 图1 模型认识 回顾一下ABAQUS的有限…...
智能电网第4期 | 电力设备全连接组网方案:从有线到无线无缝融合
随着新型电力系统建设的加速推进,电力设备通信网络正面临前所未有的挑战与机遇。在变电站自动化、输电线路监测、配电房智能化等场景中,传统通信方案已难以满足日益增长的连接需求: 环境复杂性:变电站强电磁干扰环境下需保障微秒级…...
Python 面向对象练习
不多bb了,直接上代码吧。 from pprint import pprint class Course:total_course []def __init__(self,name,id):self.name nameself.id idself.is_select FalseCourse.total_course.append(self)def __repr__(self):return (f"{__class__.__name__}("f"学…...
无感字符编码原址转换术——系统内存(Mermaid文本图表版/DeepSeek)
安全便捷无依赖,不学就会无感觉。 笔记模板由python脚本于2025-04-24 20:00:05创建,本篇笔记适合正在研究字符串编码制式的coder翻阅。 学习的细节是欢悦的历程 博客的核心价值:在于输出思考与经验,而不仅仅是知识的简单复述。 P…...
机器学习--线性回归模型
阅读本文之前,可以读一读下面这篇文章:终于有人把线性回归讲明白了 0、引言 线性回归作为统计学与机器学习的入门算法,以其简洁优雅的数学表达和直观的可解释性,在数据分析领域占据重要地位。这个诞生于19世纪的经典算法…...
HTML应用指南:利用GET请求获取微博签到位置信息
在当今数字化时代,社交媒体平台已成为人们日常生活中不可或缺的一部分。作为中国最受欢迎的社交平台之一,微博不仅为用户提供了一个分享信息、表达观点的空间,还通过其丰富的功能如签到服务,让用户能够记录自己生活中的点点滴滴。…...
如何检测Python项目哪些依赖库没有使用
要检测Python项目中哪些依赖库未被使用,可以采用以下方法: 1. 使用静态分析工具 vulture:静态分析工具,检测未使用的代码和导入 pip install vulture vulture your_project/pyflakes:检查未使用的导入语句 pip ins…...
数据仓库建设全解析!
目录 一、数据仓库建设的重要性 1. 整合企业数据资源 2. 支持企业决策制定 3. 提升企业竞争力 二、数据仓库建设的前期准备 1. 明确业务需求 2. 评估数据源 3. 制定项目计划 三、数据仓库建设的具体流程 1.需求分析 2.架构设计 3.数据建模 4.ETL 开发 5.…...
magic-api连接达梦数据库
引入依赖 然后手写驱动 <dependency><groupId>com.dameng</groupId><artifactId>DmJdbcDriver18</artifactId><version>8.1.1.193</version></dependency> jdbc:dm://127.0.0.1:5236?schemaSALES...
向量检索新选择:FastGPT + OceanBase,快速构建RAG
随着人工智能的快速发展,RAG(Retrieval-Augmented Generation,检索增强生成)技术日益受到关注。向量数据库作为 RAG 系统的核心基础设施,堪称 RAG 的“记忆中枢”,其性能直接关系到大模型生成内容的精准度与…...
WHAT - 区分 Git PR 和 MR
文章目录 PR(Pull Request)MR(Merge Request)相同点总结 git pr 和 git mr 本质上都是「合并请求」的意思,但它们对应的是不同的平台术语。 PR(Pull Request) 平台:GitHub、Bitbuc…...
Axure复选框组件的深度定制:实现自定义大小、颜色与全选功能
在产品设计中,复选框作为用户与界面交互的重要元素,其灵活性直接影响到用户体验。本文将介绍如何利用Axure RP工具,通过高级技巧实现复选框组件的自定义大小、颜色调整,以及全选功能的集成,为产品原型设计增添更多可能…...
Datawhale AI春训营——用AI帮助老人点餐
详细内容见官网链接:用AI帮助老人点餐-活动详情 | Datawhale...