哈喽哇,今天硬性分享一个我项目中的封装的table的组件以及他的使用方式之类的,为了之后用的时候可以更方便找到,话不多说直接开始
table组件:
<template>
<a-table
class="ant-table-striped"
size="middle"
:pagination="false"
:columns="columns"
:data-source="data"
:row-class-name="
(_record, index) => (index % 2 === 1 ? 'table-striped' : null)
"
>
<template v-slot:[item]="scope" v-for="item in renderArr">
<!-- // 插槽后面-slot:[item] 如果是动态渲染插槽需要使用这种方式
//renderArr 是父组件传递过来的用了插槽的名字,等下会在父组件中讲清楚,通过这个数组来遍历生成插槽 -->
<!-- //再通过这个插槽传递数据给父组件,做一些编辑提交的操作等等 -->
<slot :name="item" :scope="scope" v-bind="scope || {}"></slot>
</template>
</a-table>
</template>
<script>
import { useSlots } from 'vue'
//const slots = useSlots();
export default {
components: {},
name: 'Select',
props: {
columns: { type: Array, default: () => [] },
data: { type: Array, default: () => [] }
},
data() {
return {
value_: this.value,
renderArr: Object.keys(useSlots())
}
}
}
</script>
<style lang="less" scoped>
.ant-table-striped :deep(.table-striped) td {
background-color: #f0f5fa;
}
</style>
这个组件是一个使用了ant 库的可定制的表格,使用了<a-table>组件来创建一个表格
class = "ant-table-striped"表示为表格添加斑马纹样式,
size = "middle" 设置表格种的元素的大小为中等
:pagination = "false" 禁用表格的分页功能
:columns = columns 动态绑定表格列的定义
:data-source = “data” 动态绑定表格的数据源
:row-class-name 动态设置行的css类名,这里实现了每隔一行添加table-striped类以实现斑马纹效果
通过v-for = "item in renderArr " 循环渲染动态插槽,renderArr是从当前组件的插槽中动态获取的插槽名称数组,对于每一个插槽,使用<template v-solt:[item]>来动态声明插槽名,并通过:scope = “scope”传递作用域插槽数据,并且内部的<slot>标签用于将数据和作用域传递给父组件,允许父组件自定义这些插槽区域的内容,如编辑、删除等操作
并且同时引入了vue的useAolts Composition API ,用于获取组件的插槽信息,虽然没有直接用到,但是renderArr的定义依赖于它
定义了一个无组件的空对象在components属性中,意味着这个组件没有使用额外的子组件
组件名为select,并定义了两个props分别是用于接收列配置和数据源
在data() 函数中初始化组件状态:value_初始化为传入的value,虽然value并没有被明确的声明或者使用
renderArr初始化为当前组件插槽名的数组,通过Objlect.keys(useSlots()) 中获取
使用的某一个页面:
<template>
<!-- 一体化泵站 -->
<div
class="flex-col"
style="height: 100%; overflow-x: hidden; overflow-y: auto"
>
<div class="content-top-wrapper">
<LayoutTop>
<div class="search-wrapper flex-row justify-space-between">
<div>
<a-space>
<div>
<!-- <a-input-search
placeholder="请输入名称"
style="width: 200px"
v-model:value="searchName"
@search="onSearch"
/> -->
<Select
style="width: 200px"
v-model:value="nameValue"
:options="selWorkType.options"
:placeholder="selWorkType.placeholder"
@change="selectChange"
></Select>
</div>
<!-- <TimePicker style="width: 200px"></TimePicker> -->
<!-- <div>
<a-range-picker :value="timeValue" style="width: 200px" />
</div> -->
<div>
<a-range-picker
v-model:value="twoTime"
show-time
:placeholder="['请选择开始时间', '请选择结束时间']"
:default-value="[
dayjs().startOf('day').subtract(12, 'hour'),
dayjs().endOf('day').add(12, 'hour'),
]"
@change="searchTwoTime"
/>
</div>
</a-space>
</div>
<div>
<a-space>
<a-button type="primary" style="width: 60px" @click="jumpEchart">
<template #icon>
<LineChartOutlined />
</template>
</a-button>
<a-button type="primary" style="width: 60px" @click="Download">
<template #icon>
<UploadOutlined />
</template>
</a-button>
<!-- <a-button type="primary" style="width: 60px">
<template #icon><SearchOutlined /></template>
</a-button> -->
</a-space>
</div>
</div>
</LayoutTop>
</div>
<div class="flex-proportion content-wrapper">
<div class="table-wrapper">
<Table
:columns="columns"
:data="data"
:scroll="{ y: tableHeight }"
:loading="initLoading"
>
<template v-slot:bodyCell="{ column, index, text }">
<div
v-if="
['b1xy', 'b2xy', 'b3xy', 'gszzxy', 'gsfzxy'].includes(
column.dataIndex
)
"
>
{{
text == 0
? "停止"
: text == 1
? "运行"
: text == 2
? "故障"
: "--"
}}
</div>
<div v-if="['geshan'].includes(column.dataIndex)">
{{
text == -1
? "--"
: text == 0
? "正转"
: text == 1
? "反转"
: text == 2
? "停止"
: "故障"
}}
</div>
<div
v-if="
[
'b1lxyxtime',
'b1leijitime',
'b1dianliu',
'b2lxyxtime',
'b2leijitime',
'b2dianliu',
'b3lxyxtime',
'b3leijitime',
'b3dianliu',
'b1leijiqdcs',
'b2leijiqdcs',
'b3leijiqdcs',
'gsleijitime',
'gsdianliu',
'yewei',
'ssll',
'ljll',
'time',
].includes(column.dataIndex)
"
>
{{ text == -1 ? "--" : text }}
</div>
<div v-if="['b1gz', 'b2gz', 'b3gz'].includes(column.dataIndex)">
{{
text == -1
? "--"
: text == 1
? "变频故障"
: text == 2
? "超温漏水故障"
: text == 3
? "超时故障"
: text
}}
</div>
<div v-if="['gsgz'].includes(column.dataIndex)">
{{
text == -1
? "--"
: text == 1
? "故障"
: text == 0
? "正常"
: text
}}
</div>
<div v-if="column.dataIndex === 'title'">
{{ index + 1 }}
</div>
<div
v-if="
[
'jsgs1',
'csgs1',
'jsgs2',
'csgs2',
'bzjs',
'bzcs',
'zlgdjsf',
'zildcsf',
'ljf',
].includes(column.dataIndex)
"
>
{{
text == -1
? "--"
: text == 1
? "开到位"
: text == 2
? "关到位"
: text == 3
? "故障"
: "--"
}}
</div>
<div v-if="['gsj1', 'gsj2'].includes(column.dataIndex)">
{{
text == -1
? "--"
: text == 1
? "运行"
: text == 2
? "停止"
: text == 3
? "故障"
: "--"
}}
</div>
<div v-if="['gsywc1', 'gsywc2'].includes(column.dataIndex)">
{{ text == -1 ? "--" : "--" }}
</div>
</template>
</Table>
</div>
</div>
<div class="pagination-wrapper">
<Pagination
:total="pagination.totalCount"
:current="pagination.current"
:page-size="pagination.pageSize"
@onShowSizeChange="onShowSizeChange"
/>
</div>
</div>
</template>
<script setup>
import { ref, reactive, createVNode } from "vue";
import { useRouter } from "vue-router";
import dayjs from "dayjs";
import {
LineChartOutlined,
UploadOutlined,
SearchOutlined,
ExclamationCircleOutlined,
} from "@ant-design/icons-vue";
import { Modal } from "ant-design-vue";
// 引入接口
import { getDataPS, getQueryName } from "../api/index";
import Select from "@/components/select/index.vue";
import LayoutTop from "../../../components/layout-top/index.vue";
import TimePicker from "@/components/time-picker/index.vue";
import Table from "@/components/table/index.vue";
import Pagination from "@/components/pagination/index.vue";
import { message } from "ant-design-vue";
// 路由
const router = useRouter();
// 时间选择
const timeValue = ref();
// const twoTime = ref([null,null]);
const params = ref({});
const tableHeight = ref(document.documentElement.clientHeight - 223 + "px");
const initLoading = ref(false);
// 表格配置
const columns = reactive([
{
title: "序号",
dataIndex: "title",
width: 100,
fixed: "left",
align: "center",
},
{
title: "名称",
dataIndex: "name",
width: 200,
fixed: "left",
align: "center",
},
{ title: "1#泵状态", dataIndex: "b1xy", width: 100, align: "center" },
{ title: "2#泵状态", dataIndex: "b2xy", width: 100, align: "center" },
{ title: "3#泵状态", dataIndex: "b3xy", width: 100, align: "center" },
{ title: "格栅状态", dataIndex: "geshan", width: 100, align: "center" },
{
title: "1#泵连续运行时间",
dataIndex: "b1lxyxtime",
width: 200,
align: "center",
},
{
title: "1#泵累计运行时间",
dataIndex: "b1leijitime",
width: 200,
align: "center",
},
{
title: "1#泵电流 (A)",
dataIndex: "b1dianliu",
width: 100,
align: "center",
},
{
title: "2#泵连续运行时间",
dataIndex: "b2lxyxtime",
width: 200,
align: "center",
},
{
title: "2#泵累计运行时间",
dataIndex: "b2leijitime",
width: 200,
align: "center",
},
{
title: "2#泵电流 (A)",
dataIndex: "b2dianliu",
width: 100,
align: "center",
},
{
title: "3#泵连续运行时间",
dataIndex: "b3lxyxtime",
width: 200,
align: "center",
},
{
title: "3#泵累计运行时间",
dataIndex: "b3leijitime",
width: 200,
align: "center",
},
{
title: "3#泵电流 (A)",
dataIndex: "b3dianliu",
width: 100,
align: "center",
},
{
title: "1#泵累计启动次数",
dataIndex: "b1leijiqdcs",
width: 200,
align: "center",
},
{
title: "2#泵累计启动次数",
dataIndex: "b2leijiqdcs",
width: 200,
align: "center",
},
{
title: "3#泵累计启动次数",
dataIndex: "b3leijiqdcs",
width: 200,
align: "center",
},
{
title: "格栅累计运行时间",
dataIndex: "gsleijitime",
width: 200,
align: "center",
},
{
title: "格栅电流 (A)",
dataIndex: "gsdianliu",
width: 100,
align: "center",
},
{ title: "液位 (m)", dataIndex: "yewei", width: 100, align: "center" },
{
title: "瞬时流量 (m³/h)",
dataIndex: "ssll",
width: 100,
align: "center",
},
{ title: "累计流量 (m³)", dataIndex: "ljll", width: 100, align: "center" },
{
title: "1号格栅进水闸(G)",
dataIndex: "jsgs1",
width: 100,
align: "center",
},
{
title: "1号格栅出水闸(G)",
dataIndex: "csgs1",
width: 100,
align: "center",
},
{
title: "2号格栅进水闸(H)",
dataIndex: "jsgs2",
width: 100,
align: "center",
},
{
title: "2号格栅出水闸(H)",
dataIndex: "csgs2",
width: 100,
align: "center",
},
{ title: "泵站进水闸(D)", dataIndex: "bzjs", width: 100, align: "center" },
{ title: "泵站出水闸(D)", dataIndex: "bzcs", width: 100, align: "center" },
{
title: "自流管道进水阀(C)",
dataIndex: "zlgdjsf",
width: 100,
align: "center",
},
{
title: "自流管道出水阀(C)",
dataIndex: "zildcsf",
width: 100,
align: "center",
},
{
title: "自流管道及泵站出水管道连接阀(J)",
dataIndex: "ljf",
width: 100,
align: "center",
},
{ title: "1号格栅机", dataIndex: "gsj1", width: 100, align: "center" },
{ title: "2号格栅机", dataIndex: "gsj2", width: 100, align: "center" },
{ title: "1号格栅液位差", dataIndex: "gsywc1", width: 100, align: "center" },
{ title: "2号格栅液位差", dataIndex: "gsywc2", width: 100, align: "center" },
{ title: "监测时间", dataIndex: "time", width: 100, align: "center" },
]);
// 分页数据
const pagination = reactive({
current: 1,
pageSize: 20,
totalCount: null,
});
// 表格数据
const data = reactive([]);
// 获取表格数据
const getDataPSList = (current, pageSize, params) => {
initLoading.value = true;
getDataPS(params ? params : {}, {
current: current != undefined ? current : 1,
pageSize: pageSize != undefined ? pageSize : 20,
}).then((res) => {
// let DataPSList = res.data.result
// // 数据总条数
// pagination.totalCount = res.data.paging.total
// for (var i in DataPSList) {
// data.push(DataPSList[i])
// }
// 数据总条数
pagination.totalCount = res.data.data.total;
data.length = 0;
res.data.data.info.forEach((item) => {
data.push(item);
});
data.map((item) => {
item.b1leijiqdcs = Math.round(item.b1leijiqdcs);
item.b2leijiqdcs = Math.round(item.b2leijiqdcs);
item.b3leijiqdcs = Math.round(item.b3leijiqdcs);
// 故障信息
if (item.faultMessage == "0") {
item.faultMessage = "泵故障";
} else if (item.faultMessage == "1") {
item.faultMessage = "栅格故障";
} else if (item.faultMessage == "2") {
item.faultMessage = "变频故障";
} else if (item.faultMessage == "3") {
item.faultMessage = "超温漏水故障";
} else if (item.faultMessage == "4") {
item.faultMessage = "超时故障";
} else if (item.faultMessage == "5") {
item.faultMessage = "无";
}
});
console.log("一体化泵站数据", data);
initLoading.value = false;
});
};
getDataPSList();
// 搜索名称
const searchName = ref("");
// const onSearch = (searchValue) => {
// data.length = 0;
// params.name = searchValue;
// getDataPSList(1, 20, params);
// };
const gonextTime = ref([]);
const nameValue = ref(null);
const gonextName = ref("");
const searchTwoTime = (date, time) => {
gonextTime.value = time;
data.length = 0;
if (!date) {
delete params.startTime;
delete params.endTime;
getDataPSList(1, 20, params);
} else {
params.startTime = time[0];
params.endTime = time[1];
getDataPSList(1, 20, params);
}
};
// 分页改变是调用组件里的方法
const onShowSizeChange = (current, pageSize) => {
console.log("分页改变", current, pageSize);
pagination.current = current;
pagination.pageSize = pageSize;
data.length = 0;
getDataPSList(current, pageSize, params);
// data.length = 0;
// getDataPSList(current, 20)
};
// 跳转图表页面
const jumpEchart = () => {
// if (!(gonextTime.length && gonextName.value)) {
// message.error("请先选择查询条件再进行查看");
// // return;
// }else{
// router.push({
// name: "StationMonitorEchart",
// query: { type: "bz", time: gonextTime.value, name: gonextName.value },
// });
// }
if (gonextTime.length == "" || gonextName.value == "") {
message.error("请先选择查询条件再进行查看");
return;
} else {
router.push({
name: "StationMonitorEchart",
query: {
type: "bz",
time: [params.startTime, params.endTime],
name: gonextName.value,
},
});
}
};
// 导出
const Download = () => {
Modal.confirm({
title: "您是否确定导出一体化泵站数据?",
icon: createVNode(ExclamationCircleOutlined),
content: createVNode("div", {
style: "color:red;height:30px",
}),
onOk() {
let encodedName;
if (nameValue.value) {
// 使用replace方法替换#
encodedName = encodeURIComponent(nameValue.value.replace(/#/g, "%23"));
} else {
encodedName = nameValue.value;
}
const params = {
name: encodedName,
startTime: twoTime.value[0].format("YYYY-MM-DD HH:mm:ss"),
endTime: twoTime.value[1].format("YYYY-MM-DD HH:mm:ss"),
};
console.log("导出", params);
let url = `http://221.7.175.136:8215/api/fjj/data/DataPSExport?name=${params.name}&startTime=${params.startTime}&endTime=${params.endTime}`;
window.location.href = url;
// window.location.href =
// "http://221.7.175.136:8215/api/fjj/data/DataPSExport";
},
onCancel() {
console.log("Cancel");
},
class: "modal-pt-40",
});
};
const selWorkType = reactive({
placeholder: "请选择",
options: [],
});
const getSelList = () => {
getQueryName({ types: ["PS"] }).then((res) => {
res.data.data.forEach((item) => {
selWorkType.options.push({ value: item.NAME, label: item.NAME });
});
});
};
getSelList();
const newTime = () => {
const oneDayAgo = dayjs().startOf("day");
const twoDayAgo = dayjs().endOf("day");
const formattedTime1 = oneDayAgo.format("YYYY-MM-DD HH:mm:ss");
const formattedTime2 = twoDayAgo.format("YYYY-MM-DD HH:mm:ss");
// params.value.startTime = formattedTime1;
// params.value.endTime = formattedTime2;
gonextTime.value = [formattedTime1, formattedTime2];
};
// 初始化时间范围选择器的值
// const twoTime = ref([
// dayjs().startOf('day').subtract(12, 'hour'),
// dayjs().endOf('day').add(12, 'hour'),
// ]);
const twoTime = ref([]);
const selectChange = (searchValue) => {
if (searchValue) {
twoTime.value = [dayjs().startOf("day"), dayjs().endOf("day")];
newTime();
} else {
twoTime.value = []; // 若未选择或取消选择,则清空时间范围
}
gonextName.value = searchValue;
gonextTime.value = [dayjs().startOf("day"), dayjs().endOf("day")];
// 在这里重新设置默认的 24 小时时间范围
// twoTime.value = [dayjs().startOf('day'), dayjs().endOf('day')];
data.length = 0;
params.name = searchValue;
params.startTime = gonextTime.value[0].format("YYYY-MM-DD HH:mm:ss");
params.endTime = gonextTime.value[1].format("YYYY-MM-DD HH:mm:ss");
getDataPSList(1, 20, params);
};
</script>
<style lang="less" scoped>
:deep(.ant-input) {
height: 32px !important;
border: 0;
background: #f0f5fa;
}
:deep(.ant-input-search-button) {
height: 32px !important;
border: 0;
background: #f0f5fa;
width: 40px !important;
}
.search-wrapper {
line-height: 32px;
}
.content-wrapper {
.table-wrapper {
background: white;
border-radius: 15px;
height: 100%;
padding: 5px;
}
}
.pagination-wrapper {
height: 70px;
padding: 10px 0;
}
</style>
使用时,就正常的按照路径引入,然后使用就可以了,定义的columns就是传给子组件的具体的内容了,在不同的引入子组件的页面中,进行不同的columns的设置就可以实现一个不完全相同的效果,当然还有一些其他的功能也都在,可以借鉴参考
这篇文章就先这样啦~~~~