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

300 lines
9.6 KiB
Vue
Raw Normal View History

2025-10-23 19:20:08 +08:00
<template>
<!-- 右侧表格 -->
<div>
<el-card style="min-height: calc(100vh - 125px)">
<!-- 查询 -->
<el-form size="small" ref="queryForm" :inline="true" :model="queryParams">
2025-11-07 14:19:20 +08:00
<el-form-item prop="fileName">
<el-input clearable placeholder="请输入文件名称" v-model="queryParams.fileName"
2025-10-23 19:20:08 +08:00
@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: {
2025-11-07 14:19:20 +08:00
fileName: undefined,
2025-10-23 19:20:08 +08:00
},
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[0] && this.columns[0].prop
if (!targetProp) return
2025-11-07 14:19:20 +08:00
const keyword = String(this.queryParams.fileName || '').trim()
console.log(keyword+"keyword")
2025-10-23 19:20:08 +08:00
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() {
2025-11-07 14:19:20 +08:00
this.queryParams = { fileName: undefined }
2025-10-23 19:20:08 +08:00
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>