smart_archives_web/src/views/data-collect/file-share-manage/components/right-table.vue

299 lines
9.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 右侧表格 -->
<div>
<el-card style="min-height: calc(100vh - 125px)">
<!-- 查询 -->
<el-form size="small" ref="queryForm" :inline="true" :model="queryParams">
<el-form-item prop="dataTypeName">
<el-input clearable placeholder="请输入文件名称" v-model="queryParams.dataTypeName"
@keyup.enter.native="onHandleQuery" />
</el-form-item>
<el-form-item>
<el-button size="mini" type="primary" icon="el-icon-search" @click="onHandleQuery">
查询
</el-button>
<el-button size="mini" icon="el-icon-refresh" @click="onResetQuery">
重置
</el-button>
</el-form-item>
</el-form>
<!-- 表格 -->
<el-table :data="filteredTableData" border :height="tableHeight" style="width: 100%" header-align="center">
<el-table-column v-if="tableData && tableData.length" type="index" label="序号" width="60" align="center" />
<el-table-column align="center" :key="column.prop" :prop="column.prop" :label="column.label"
v-for="column in columns" />
<el-table-column v-if="tableData && tableData.length" label="操作" width="100" align="center" class-name="action-col" label-class-name="action-col-header">
<template slot-scope="{ row }">
<el-button plain type="primary" size="mini" class="action-btn" icon="el-icon-share" @click="handleShare(row)" v-hasPermi="['file:Collect:share']">分享</el-button>
</template>
</el-table-column>
</el-table>
<Share v-if="isflag" :rowData="row" :title="title"
@closeDialog="closeDialog" @showColose="showColose" :dataForm="row" :disabled="loading" :width="600" />
</el-card>
</div>
</template>
<script>
import { getListDataSetAPI } from '@/api/data-collect/file-share-manage'
import Share from './share.vue'
import { validSecurity } from '@/utils/validate'
export default {
name: 'RightTable',
components: {
Share
},
props: {
selectedNodeId: {
type: [Number, String],
default: 0,
},
selectedNodeName: {
type: [String],
default: '',
},
},
data() {
return {
isflag: false,
loading: false,
row: {},
title: '分享',
queryParams: {
dataTypeName: undefined,
},
tableData: [],
columns: [],
tableHeight: 400,
filteredManual: null,
}
},
computed: {
// 按第二个字段进行本地过滤
filteredTableData() {
// 仅在点击“查询”后使用过滤结果;输入变化不自动过滤
if (Array.isArray(this.filteredManual)) return this.filteredManual
return this.tableData
},
},
methods: {
// 分享
handleShare(row) {
// console.log(row);
this.isflag = true;
row.selectedNodeName = this.selectedNodeName;
row.selectedNodeId = this.selectedNodeId;
row.jsonId = row.id;
this.row = row;
},
closeDialog() {
this.isflag = false;
},
showColose() {
this.isflag = false;
},
// 查询:按第一列字段做模糊匹配
onHandleQuery() {
if (!Array.isArray(this.columns) || this.columns.length < 1) return
const targetProp = this.columns[1] && this.columns[1].prop
if (!targetProp) return
const keyword = String(this.queryParams.dataTypeName || '').trim()
if (!keyword) {
// 空关键字还原
this.filteredManual = null
return
}
// 安全校验
if (!validSecurity(keyword)) {
this.$message.error('搜索内容包含非法字符,请重新输入')
return
}
// 执行一次性本地过滤
const source = Array.isArray(this.tableData) ? this.tableData : []
const kw = keyword.toLowerCase()
this.filteredManual = source.filter(row => {
const val = row && targetProp in row ? row[targetProp] : ''
return String(val ?? '').toLowerCase().includes(kw)
})
// 触发一次高度计算,避免数据量变化造成滚动体验不佳
this.computeTableHeight()
},
// 重置
onResetQuery() {
this.queryParams = { dataTypeName: undefined }
this.filteredManual = null
this.computeTableHeight()
},
// 获取数据列表
async getListDataSetClassFun(node) {
const params = {
dataClassifyId: node,
}
const res = await getListDataSetAPI(params)
// 安全解析与渲染
this.columns = []
this.tableData = []
if (!res || !Array.isArray(res.rows) || res.rows.length === 0) {
this.forceTableLayout()
return
}
const firstRow = res.rows[0]
if (!firstRow || !firstRow.dataJson) {
this.forceTableLayout()
return
}
let dataList = []
try {
dataList = JSON.parse(firstRow.dataJson)
} catch (e) {
console.warn('数据集 dataJson 解析失败:', e)
this.forceTableLayout()
return
}
if (!Array.isArray(dataList) || dataList.length === 0) {
this.forceTableLayout()
return
}
const [header, ...rows] = dataList
if (header && typeof header === 'object') {
this.columns = Object.entries(header)
.filter(([prop]) => String(prop).toLowerCase() !== 'id')
.map(([prop, label], index) => ({
label: String(label),
prop: String(prop),
width: index === 0 ? '120' : undefined,
align: index === 0 ? 'left' : 'center',
}))
}
const propOrder = this.columns.map(c => c.prop)
this.tableData = rows.map(row => {
if (Array.isArray(row)) {
const obj = {}
for (let i = 0; i < propOrder.length; i++) {
obj[propOrder[i]] = row[i]
}
return obj
}
return row || {}
})
this.forceTableLayout()
},
// 强制表格重新布局
forceTableLayout() {
this.$nextTick(() => {
setTimeout(() => {
// 获取表格实例并调用 doLayout
const table = this.$el.querySelector('.el-table')
if (table && table.__vue__) {
table.__vue__.doLayout()
}
this.computeTableHeight()
}, 100)
})
},
// 计算表格高度(使用固定 height滚动更顺滑
computeTableHeight() {
this.$nextTick(() => {
const topOffset = this.$el ? this.$el.getBoundingClientRect().top : 0
const formHeight = this.$refs.queryForm && this.$refs.queryForm.$el
? this.$refs.queryForm.$el.offsetHeight
: 0
// 额外预留:卡片内边距、表格头部等
const extra = 100
const available = window.innerHeight - topOffset - formHeight - extra
this.tableHeight = Math.max(260, available)
})
},
},
// 监听选中的节点ID
watch: {
selectedNodeId: {
handler(newVal) {
this.columns = []
this.tableData = []
this.getListDataSetClassFun(newVal)
},
immediate: true, // 表示立即执行
},
selectedNodeName: {
handler(newVal2) {
this.selectedNodeName = newVal2
},
immediate: true, // 表示立即执行
},
},
mounted() {
const onResize = () => this.computeTableHeight()
this.computeTableHeight()
window.addEventListener('resize', onResize)
this.$once('hook:beforeDestroy', () => {
window.removeEventListener('resize', onResize)
})
},
}
</script>
<style scoped>
/* 加粗表格滚动条 */
::v-deep .el-table__body-wrapper::-webkit-scrollbar,
::v-deep .el-table__fixed-body-wrapper::-webkit-scrollbar {
width: 10px; /* 垂直滚动条宽度 */
height: 10px; /* 水平滚动条高度 */
}
::v-deep .el-table__body-wrapper::-webkit-scrollbar-track,
::v-deep .el-table__fixed-body-wrapper::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 6px;
}
::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb,
::v-deep .el-table__fixed-body-wrapper::-webkit-scrollbar-thumb {
background: #bfbfbf;
border-radius: 6px;
}
::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb:hover,
::v-deep .el-table__fixed-body-wrapper::-webkit-scrollbar-thumb:hover {
background: #a6a6a6;
}
/* 操作列样式统一,避免按钮受表格行样式影响抖动或换行 */
/* 操作列单元格与其它列统一高度与内边距,避免不对齐 */
::v-deep .action-col .cell {
display: flex;
align-items: center;
justify-content: center;
padding: 0 8px !important;
height: 100%;
}
::v-deep .action-col-header .cell {
font-weight: 600;
}
.action-btn {
padding: 3px 8px;
line-height: 1;
}
</style>