Commit 65e7e260 authored by Cai Wei's avatar Cai Wei

feat(*): 添加公共表格组件

parent 93831a15
......@@ -13,6 +13,7 @@
"echarts": "^5.6.0",
"element-plus": "^2.9.10",
"js-cookie": "^3.0.5",
"nprogress": "^0.2.0",
"path": "^0.12.7",
"pinia": "^3.0.2",
"qs": "^6.14.0",
......@@ -2133,6 +2134,11 @@
"integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==",
"license": "BSD-3-Clause"
},
"node_modules/nprogress": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz",
"integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA=="
},
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz",
......
<template>
<div class="common-table">
<el-table :data="currentPageData" v-bind="$attrs" style="width: 100%">
<template v-for="column in columns" :key="column.prop">
<el-table-column v-bind="column">
<template #default="scope">
<slot
:name="column.prop"
v-bind="scope"
:row="scope.row"
:column="column"
>
{{ scope.row[column.prop] }}
</slot>
</template>
</el-table-column>
</template>
</el-table>
<div class="pagination-container" v-if="showPagination">
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="pageSizes"
:total="total"
layout="total, prev, pager, next, sizes, jumper"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:total-text="paginationTexts.total || '总计'"
:size-change-text="paginationTexts.sizeChange || '条/页'"
:jumper-text="paginationTexts.jumper || '前往'"
>
</el-pagination>
</div>
</div>
</template>
<script setup>
import { ref, computed, watch } from "vue";
const props = defineProps({
// 表格数据
data: {
type: Array,
required: true,
default: () => [],
},
// 列配置
columns: {
type: Array,
required: true,
default: () => [],
},
// 是否显示分页
showPagination: {
type: Boolean,
default: true,
},
// 分页大小选项
pageSizes: {
type: Array,
default: () => [10, 20, 30, 50],
},
// 默认每页条数
defaultPageSize: {
type: Number,
default: 10,
},
// 分页布局
paginationLayout: {
type: String,
default: "total, sizes, prev, pager, next, jumper",
},
// 分页器文字配置
paginationTexts: {
type: Object,
default: () => ({
total: "总计", // 总计xxx条
sizeChange: "条/页", // 每页显示数量的文字
prev: "上一页",
next: "下一页",
jumper: "前往", // 跳转文字
}),
},
});
const emit = defineEmits([
"update:current-page",
"update:page-size",
"pagination-change",
]);
// 分页相关
const currentPage = ref(1);
const pageSize = ref(props.defaultPageSize);
const total = computed(() => props.data.length);
// 当前页数据
const currentPageData = computed(() => {
if (!props.showPagination) return props.data;
const start = (currentPage.value - 1) * pageSize.value;
const end = start + pageSize.value;
return props.data.slice(start, end);
});
// 分页事件处理
const handleSizeChange = (val) => {
pageSize.value = val;
currentPage.value = 1;
emitPaginationChange();
};
const handleCurrentChange = (val) => {
currentPage.value = val;
emitPaginationChange();
};
// 向父组件发送分页变化事件
const emitPaginationChange = () => {
emit("pagination-change", {
currentPage: currentPage.value,
pageSize: pageSize.value,
total: total.value,
});
emit("update:current-page", currentPage.value);
emit("update:page-size", pageSize.value);
};
// 监听数据变化,重置分页
watch(
() => props.data,
() => {
currentPage.value = 1;
},
{ deep: true }
);
</script>
<style lang="scss" scoped>
.common-table {
.pagination-container {
margin-top: 20px;
display: flex;
justify-content: flex-end;
padding: 10px 0;
}
}
</style>
<style lang="scss">
.el-table__header,
.el-table__body {
width: 100% !important;
}
</style>
import zhCn from "element-plus/dist/locale/zh-cn.mjs";
export default {
...zhCn,
el: {
...zhCn.el,
pagination: {
goto: "前往",
pagesize: "条/页",
total: "总共{total}条",
pageClassifier: "页",
},
},
};
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import { router } from './router'
import '@/router/routePermission.js'
import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";
import { router } from "./router";
import "@/router/routePermission.js";
import zhCustom from "@/locale/zh-custom";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
import { createPinia } from "pinia";
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import { createPinia } from 'pinia'
const app = createApp(App)
const app = createApp(App);
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
app.component(key, component);
}
app.use(router).use(ElementPlus).use(createPinia()).mount('#app')
app
.use(router)
.use(ElementPlus, { locale: zhCustom })
.use(createPinia())
.mount("#app");
......@@ -67,20 +67,47 @@
</el-form>
</div>
<el-table :data="tableData" style="width: 100%">
<el-table-column
v-for="item in tableColumns"
:key="item.prop"
:prop="item.prop"
:label="item.label"
/>
</el-table>
<common-table
:data="tableData"
:columns="tableColumns"
:default-page-size="10"
@pagination-change="handlePaginationChange"
:pagination-texts="{
total: '共',
sizeChange: '条/页',
prev: '前一页',
next: '后一页',
jumper: '跳至',
}"
>
<template #status="{ row }">
<el-tag :type="getStatusType(row.status)" effect="light">
{{ row.status }}
</el-tag>
</template>
<template #healthScore="{ row }">
<span :style="{ color: getHealthScoreColor(row.healthScore) }">
{{ row.healthScore }}
</span>
</template>
<template #operation="{ row }">
<el-button type="primary" link @click="handleView(row)">
查看详情
</el-button>
<el-button type="primary" link @click="handleEdit(row)">
编辑
</el-button>
</template>
</common-table>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, computed, nextTick } from "vue";
import { ref, onMounted, onBeforeUnmount } from "vue";
import CommonTable from "@/components/CommonTable/index.vue";
const formInline = ref({
deviceName: "",
......@@ -100,74 +127,141 @@ const options = ref([
const tableColumns = ref([
{
prop: "date",
label: "Date",
prop: "deviceName",
label: "除尘器名称",
width: "15%",
},
{
prop: "process",
label: "工序",
width: "10%",
},
{
prop: "healthScore",
label: "健康度",
width: "10%",
},
{
prop: "status",
label: "运行状态",
width: "10%",
},
{
prop: "alarmCount",
label: "告警数量",
width: "10%",
},
{
prop: "lastAlarmTime",
label: "最近告警时间",
width: "15%",
},
{
prop: "name",
label: "Name",
prop: "location",
label: "安装位置",
width: "15%",
},
{
prop: "operation",
label: "操作",
width: "15%",
},
]);
const tableData = [
{
date: "2016-05-03",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
deviceName: "1#除尘器",
process: "转炉",
healthScore: "98%",
status: "正常运行",
alarmCount: 0,
lastAlarmTime: "-",
location: "一号转炉东侧",
},
{
date: "2016-05-02",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
deviceName: "2#除尘器",
process: "转炉",
healthScore: "45%",
status: "故障",
alarmCount: 2,
lastAlarmTime: "2024-03-19 14:30",
location: "二号转炉西侧",
},
{
date: "2016-05-04",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
deviceName: "3#除尘器",
process: "炼铁",
healthScore: "78%",
status: "轻微异常",
alarmCount: 1,
lastAlarmTime: "2024-03-19 10:15",
location: "炼铁区域北侧",
},
{
date: "2016-05-01",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
deviceName: "4#除尘器",
process: "炼铁",
healthScore: "89%",
status: "正常运行",
alarmCount: 0,
lastAlarmTime: "-",
location: "炼铁区域南侧",
},
{
date: "2016-05-08",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
deviceName: "5#除尘器",
process: "转炉",
healthScore: "92%",
status: "正常运行",
alarmCount: 0,
lastAlarmTime: "-",
location: "三号转炉东侧",
},
{
date: "2016-05-06",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
deviceName: "6#除尘器",
process: "炼铁",
healthScore: "95%",
status: "正常运行",
alarmCount: 0,
lastAlarmTime: "-",
location: "炼铁区域东侧",
},
{
date: "2016-05-07",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
deviceName: "7#除尘器",
process: "转炉",
healthScore: "87%",
status: "正常运行",
alarmCount: 0,
lastAlarmTime: "-",
location: "四号转炉西侧",
},
];
const getStatusType = (status) => {
const statusMap = {
正常运行: "success",
轻微异常: "warning",
故障: "danger",
};
return statusMap[status] || "info";
};
const getHealthScoreColor = (score) => {
const value = parseInt(score);
if (value >= 90) return "#67C23A";
if (value >= 70) return "#E6A23C";
return "#F56C6C";
};
const handleView = (row) => {
console.log("查看详情", row);
};
const handleEdit = (row) => {
console.log("编辑", row);
};
const handlePaginationChange = (pagination) => {
console.log("分页变化", pagination);
};
const onSubmit = () => {
console.log("submit!", formInline.value);
};
......@@ -185,7 +279,6 @@ onBeforeUnmount(() => {});
.header {
display: flex;
// justify-content: space-between;
align-items: center;
gap: 16px;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment